m6502,tms57002: Snakes in an emulator [Robert Muth, O. Galibert]

This commit is contained in:
Olivier Galibert 2012-12-06 19:08:40 +00:00
parent b4d0dde34a
commit 627ac29a1a
6 changed files with 721 additions and 1265 deletions

2
.gitattributes vendored
View File

@ -506,7 +506,6 @@ src/emu/cpu/m6502/m4510.h svneol=native#text/plain
src/emu/cpu/m6502/m6502.c svneol=native#text/plain
src/emu/cpu/m6502/m6502.h svneol=native#text/plain
src/emu/cpu/m6502/m6502.txt svneol=native#text/plain
src/emu/cpu/m6502/m6502make.c svneol=native#text/plain
src/emu/cpu/m6502/m6502make.py svneol=native#text/plain
src/emu/cpu/m6502/m6504.c svneol=native#text/plain
src/emu/cpu/m6502/m6504.h svneol=native#text/plain
@ -802,7 +801,6 @@ src/emu/cpu/tms57002/tms57002.c svneol=native#text/plain
src/emu/cpu/tms57002/tms57002.h svneol=native#text/plain
src/emu/cpu/tms57002/tms57kdec.c svneol=native#text/plain
src/emu/cpu/tms57002/tmsinstr.lst svneol=native#text/plain
src/emu/cpu/tms57002/tmsmake.c svneol=native#text/plain
src/emu/cpu/tms57002/tmsmake.py svneol=native#text/plain
src/emu/cpu/tms7000/7000dasm.c svneol=native#text/plain
src/emu/cpu/tms7000/tms7000.c svneol=native#text/plain

View File

@ -1018,7 +1018,6 @@ CPUOBJS += $(CPUOBJ)/m6502/deco16.o \
$(CPUOBJ)/m6502/n2a03.o \
$(CPUOBJ)/m6502/r65c02.o
DASMOBJS +=
M6502MAKE += $(BUILDOUT)/m6502make$(BUILD_EXE)
endif
$(CPUOBJ)/m6502/deco16.o: $(CPUSRC)/m6502/deco16.c \
@ -1094,53 +1093,41 @@ $(CPUOBJ)/m6502/r65c02.o: $(CPUSRC)/m6502/r65c02.c \
$(CPUSRC)/m6502/m6502.h
# rule to generate the C files
$(CPUOBJ)/m6502/deco16.inc: $(M6502MAKE) $(CPUSRC)/m6502/odeco16.lst $(CPUSRC)/m6502/ddeco16.lst
$(CPUOBJ)/m6502/deco16.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/odeco16.lst $(CPUSRC)/m6502/ddeco16.lst
@echo Generating DECO16 source file...
$(M6502MAKE) deco16_device $(CPUSRC)/m6502/odeco16.lst $(CPUSRC)/m6502/ddeco16.lst $@
$(CPUSRC)/m6502/m6502make.py deco16_device $(CPUSRC)/m6502/odeco16.lst $(CPUSRC)/m6502/ddeco16.lst $@
$(CPUOBJ)/m6502/m4510.inc: $(M6502MAKE) $(CPUSRC)/m6502/om4510.lst $(CPUSRC)/m6502/dm4510.lst
$(CPUOBJ)/m6502/m4510.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/om4510.lst $(CPUSRC)/m6502/dm4510.lst
@echo Generating M4510 source file...
$(M6502MAKE) m4510_device $(CPUSRC)/m6502/om4510.lst $(CPUSRC)/m6502/dm4510.lst $@
$(CPUSRC)/m6502/m6502make.py m4510_device $(CPUSRC)/m6502/om4510.lst $(CPUSRC)/m6502/dm4510.lst $@
$(CPUOBJ)/m6502/m6502.inc: $(M6502MAKE) $(CPUSRC)/m6502/om6502.lst $(CPUSRC)/m6502/dm6502.lst
$(CPUOBJ)/m6502/m6502.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/om6502.lst $(CPUSRC)/m6502/dm6502.lst
@echo Generating M6502 source file...
$(M6502MAKE) m6502_device $(CPUSRC)/m6502/om6502.lst $(CPUSRC)/m6502/dm6502.lst $@
$(CPUSRC)/m6502/m6502make.py m6502_device $(CPUSRC)/m6502/om6502.lst $(CPUSRC)/m6502/dm6502.lst $@
$(CPUOBJ)/m6502/m65c02.inc: $(M6502MAKE) $(CPUSRC)/m6502/om65c02.lst $(CPUSRC)/m6502/dm65c02.lst
$(CPUOBJ)/m6502/m65c02.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/om65c02.lst $(CPUSRC)/m6502/dm65c02.lst
@echo Generating M65C02 source file...
$(M6502MAKE) m65c02_device $(CPUSRC)/m6502/om65c02.lst $(CPUSRC)/m6502/dm65c02.lst $@
$(CPUSRC)/m6502/m6502make.py m65c02_device $(CPUSRC)/m6502/om65c02.lst $(CPUSRC)/m6502/dm65c02.lst $@
$(CPUOBJ)/m6502/m65ce02.inc: $(M6502MAKE) $(CPUSRC)/m6502/om65ce02.lst $(CPUSRC)/m6502/dm65ce02.lst
$(CPUOBJ)/m6502/m65ce02.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/om65ce02.lst $(CPUSRC)/m6502/dm65ce02.lst
@echo Generating M65CE02 source file...
$(M6502MAKE) m65ce02_device $(CPUSRC)/m6502/om65ce02.lst $(CPUSRC)/m6502/dm65ce02.lst $@
$(CPUSRC)/m6502/m6502make.py m65ce02_device $(CPUSRC)/m6502/om65ce02.lst $(CPUSRC)/m6502/dm65ce02.lst $@
$(CPUOBJ)/m6502/m6509.inc: $(M6502MAKE) $(CPUSRC)/m6502/om6509.lst $(CPUSRC)/m6502/dm6509.lst
$(CPUOBJ)/m6502/m6509.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/om6509.lst $(CPUSRC)/m6502/dm6509.lst
@echo Generating M6509 source file...
$(M6502MAKE) m6509_device $(CPUSRC)/m6502/om6509.lst $(CPUSRC)/m6502/dm6509.lst $@
$(CPUSRC)/m6502/m6502make.py m6509_device $(CPUSRC)/m6502/om6509.lst $(CPUSRC)/m6502/dm6509.lst $@
$(CPUOBJ)/m6502/m6510.inc: $(M6502MAKE) $(CPUSRC)/m6502/om6510.lst $(CPUSRC)/m6502/dm6510.lst
$(CPUOBJ)/m6502/m6510.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/om6510.lst $(CPUSRC)/m6502/dm6510.lst
@echo Generating M6510 source file...
$(M6502MAKE) m6510_device $(CPUSRC)/m6502/om6510.lst $(CPUSRC)/m6502/dm6510.lst $@
$(CPUSRC)/m6502/m6502make.py m6510_device $(CPUSRC)/m6502/om6510.lst $(CPUSRC)/m6502/dm6510.lst $@
$(CPUOBJ)/m6502/n2a03.inc: $(M6502MAKE) $(CPUSRC)/m6502/on2a03.lst $(CPUSRC)/m6502/dn2a03.lst
$(CPUOBJ)/m6502/n2a03.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/on2a03.lst $(CPUSRC)/m6502/dn2a03.lst
@echo Generating N2A03 source file...
$(M6502MAKE) n2a03_device $(CPUSRC)/m6502/on2a03.lst $(CPUSRC)/m6502/dn2a03.lst $@
$(CPUSRC)/m6502/m6502make.py n2a03_device $(CPUSRC)/m6502/on2a03.lst $(CPUSRC)/m6502/dn2a03.lst $@
$(CPUOBJ)/m6502/r65c02.inc: $(M6502MAKE) $(CPUSRC)/m6502/dr65c02.lst
$(CPUOBJ)/m6502/r65c02.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/dr65c02.lst
@echo Generating R65C02 source file...
$(M6502MAKE) r65c02_device - $(CPUSRC)/m6502/dr65c02.lst $@
# rule to build the generator
ifneq ($(CROSS_BUILD),1)
BUILD += $(M6502MAKE)
$(M6502MAKE): $(CPUOBJ)/m6502/m6502make.o $(LIBOCORE)
@echo Linking $@...
$(LD) $(LDFLAGS) $(OSDBGLDFLAGS) $^ $(LIBS) -o $@
endif
$(CPUSRC)/m6502/m6502make.py r65c02_device - $(CPUSRC)/m6502/dr65c02.lst $@
#-------------------------------------------------
@ -1843,9 +1830,6 @@ ifneq ($(filter TMS57002,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/tms57002
CPUOBJS += $(CPUOBJ)/tms57002/tms57002.o $(CPUOBJ)/tms57002/tms57kdec.o
DASMOBJS += $(CPUOBJ)/tms57002/57002dsm.o
ifndef TMSMAKE
TMSMAKE += $(BUILDOUT)/tmsmake$(BUILD_EXE)
endif
endif
$(CPUOBJ)/tms57002/tms57002.o: $(CPUSRC)/tms57002/tms57002.c \
@ -1860,20 +1844,9 @@ $(CPUOBJ)/tms57002/57002dsm.o: $(CPUSRC)/tms57002/57002dsm.c \
$(CPUOBJ)/tms57002/tms57002.inc
# rule to generate the C file
$(CPUOBJ)/tms57002/tms57002.inc: $(TMSMAKE) $(CPUSRC)/tms57002/tmsinstr.lst
$(CPUOBJ)/tms57002/tms57002.inc: $(CPUSRC)/tms57002/tmsmake.py $(CPUSRC)/tms57002/tmsinstr.lst
@echo Generating TMS57002 source file...
$(TMSMAKE) $(CPUSRC)/tms57002/tmsinstr.lst $@
# rule to build the generator
ifneq ($(CROSS_BUILD),1)
BUILD += $(TMSMAKE)
$(TMSMAKE): $(CPUOBJ)/tms57002/tmsmake.o $(LIBOCORE)
@echo Linking $@...
$(LD) $(LDFLAGS) $(OSDBGLDFLAGS) $^ $(LIBS) -o $@
endif
$(CPUSRC)/tms57002/tmsmake.py $(CPUSRC)/tms57002/tmsinstr.lst $@
#-------------------------------------------------

View File

@ -1,257 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdarg.h>
#include <ctype.h>
#include "osdcomm.h"
#include <string>
#include <vector>
using namespace std;
enum { STATES = 0x101 };
const char *snames[STATES-0x100] = {
"STATE_RESET"
};
struct opcode {
string name;
vector<string> instructions;
};
vector<opcode> opcodes;
struct table_t {
string opcodes[STATES];
};
table_t table;
string device_name;
static void load_opcodes(const char *fname)
{
char buf[4096];
FILE *f;
sprintf(buf, "Error opening %s for reading\n", fname);
f = fopen(fname, "r");
if(!f) {
perror(buf);
exit(1);
}
while(fgets(buf, sizeof(buf), f)) {
char *p = buf;
if(p[0] == '#' || p[0] == '\r' || p[0] == '\n' || p[0] == 0)
continue;
for(char *q = p; *q; q++)
if(*q == '\r' || *q == '\n') {
*q = 0;
break;
}
if(p[0] != ' ' && p[0] != '\t') {
opcodes.resize(opcodes.size()+1);
opcodes.back().name = p;
} else
opcodes.back().instructions.push_back(p);
}
fclose(f);
}
static void load_disp(const char *fname)
{
char buf[4096];
FILE *f;
sprintf(buf, "Error opening %s for reading\n", fname);
f = fopen(fname, "r");
if(!f) {
perror(buf);
exit(1);
}
int state = 0;
while(fgets(buf, sizeof(buf), f)) {
char *p = buf;
if(p[0] == '#' || p[0] == '\r' || p[0] == '\n' || p[0] == 0)
continue;
while(state < STATES) {
while(*p && (*p == '\n' || *p == '\r' || *p == ' ' || *p == '\t'))
p++;
if(!*p)
break;
char *q = p;
while(*p != '\n' && *p != '\r' && *p != ' ' && *p != '\t')
p++;
table.opcodes[state++] = string(q, p);
}
}
fclose(f);
}
enum { NONE, EAT_ALL, MEMORY };
static int identify_line_type(string inst)
{
if(inst.find("eat-all-cycles") != string::npos)
return EAT_ALL;
if(inst.find("read") != string::npos ||
inst.find("write") != string::npos ||
inst.find("prefetch(") != string::npos ||
inst.find("prefetch_noirq(") != string::npos)
return MEMORY;
return NONE;
}
static void save_opcodes(FILE *f)
{
for(unsigned int i=0; i != opcodes.size(); i++) {
int substate;
opcode &o = opcodes[i];
fprintf(f, "void %s::%s_full()\n", device_name.c_str(), o.name.c_str());
fprintf(f, "{\n");
substate = 1;
for(unsigned int j=0; j != o.instructions.size(); j++) {
string inst = o.instructions[j];
int type = identify_line_type(inst);
if(type == EAT_ALL) {
fprintf(f, "\ticount=0; inst_substate = %d; return;", substate);
substate++;
} else {
if(type == MEMORY)
fprintf(f, "\tif(icount == 0) { inst_substate = %d; return; }\n", substate);
fprintf(f, "%s\n", inst.c_str());
if(type == MEMORY) {
fprintf(f, "\ticount--;\n");
substate++;
}
}
}
fprintf(f, "}\n");
fprintf(f, "void %s::%s_partial()\n", device_name.c_str(), o.name.c_str());
fprintf(f, "{\n");
fprintf(f, "switch(inst_substate) {\n");
fprintf(f, "case 0:\n");
substate = 1;
for(unsigned int j=0; j != o.instructions.size(); j++) {
string inst = o.instructions[j];
int type = identify_line_type(inst);
if(type == EAT_ALL) {
fprintf(f, "\ticount=0; inst_substate = %d; return;", substate);
fprintf(f, "case %d:;\n", substate);
substate++;
} else {
if(type == MEMORY) {
fprintf(f, "\tif(icount == 0) { inst_substate = %d; return; }\n", substate);
fprintf(f, "case %d:\n", substate);
}
fprintf(f, "%s\n", inst.c_str());
if(type == MEMORY) {
fprintf(f, "\ticount--;\n");
substate++;
}
}
}
fprintf(f, "}\n");
fprintf(f, "\tinst_substate = 0;\n");
fprintf(f, "}\n");
fprintf(f, "\n");
}
fprintf(f, "\n");
}
static void save_tables(FILE *f)
{
fprintf(f, "void %s::do_exec_full()\n", device_name.c_str());
fprintf(f, "{\n");
fprintf(f, "\tswitch(inst_state) {\n");
for(int j=0; j<STATES; j++) {
if(table.opcodes[j] != ".") {
if(j < 0x100)
fprintf(f, "\tcase 0x%02x: %s_full(); break;\n", j, table.opcodes[j].c_str());
else
fprintf(f, "\tcase %s: %s_full(); break;\n", snames[j-0x100], table.opcodes[j].c_str());
}
}
fprintf(f, "\t}\n");
fprintf(f, "}\n");
fprintf(f, "void %s::do_exec_partial()\n", device_name.c_str());
fprintf(f, "{\n");
fprintf(f, "\tswitch(inst_state) {\n");
for(int j=0; j<STATES; j++) {
if(table.opcodes[j] != ".") {
if(j < 0x100)
fprintf(f, "\tcase 0x%02x: %s_partial(); break;\n", j, table.opcodes[j].c_str());
else
fprintf(f, "\tcase %s: %s_partial(); break;\n", snames[j-0x100], table.opcodes[j].c_str());
}
}
fprintf(f, "\t}\n");
fprintf(f, "}\n");
fprintf(f, "const %s::disasm_entry %s::disasm_entries[0x100] = {\n", device_name.c_str(), device_name.c_str());
for(int j=0; j<0x100; j++)
if(table.opcodes[j] != ".") {
string opcode = table.opcodes[j];
string opc, fullopc, mode;
string::iterator k, ke;
for(k = opcode.begin(); k != opcode.end() && *k != '_'; k++);
for(ke = opcode.end(); ke != opcode.begin() && ke[-1] != '_'; ke--);
assert(k != opcode.end());
opc = string(opcode.begin(), k);
fullopc = string(opcode.begin(), ke-1);
mode = string(ke, opcode.end());
bool step_over = opc == "jsr" || opc == "bsr";
bool step_out = opc == "rts" || opc == "rti" || opc == "rtn";
fprintf(f, "\t{ \"%s\", DASM_%s, %s },\n",
opc.c_str(), mode.c_str(), step_over ? "DASMFLAG_STEP_OVER" : step_out ? "DASMFLAG_STEP_OUT" : "0");
} else
fprintf(f, "\t{ \"???\", DASM_imp, 0, false },\n");
fprintf(f, "};\n");
}
static void save(const char *fname)
{
char buf[4096];
FILE *f;
sprintf(buf, "Error opening %s for writing\n", fname);
f = fopen(fname, "w");
if(!f) {
perror(buf);
exit(1);
}
save_opcodes(f);
save_tables(f);
fclose(f);
}
int main(int argc, char *argv[])
{
if(argc != 5) {
fprintf(stderr, "Usage:\n%s device_name {opc.lst|-} disp.lst device.inc\n", argv[0]);
exit(1);
}
device_name = argv[1];
if(strcmp(argv[2], "-"))
load_opcodes(argv[2]);
load_disp(argv[3]);
save(argv[4]);
return 0;
}

273
src/emu/cpu/m6502/m6502make.py Normal file → Executable file
View File

@ -0,0 +1,273 @@
#!/usr/bin/python
USAGE = """
Usage:
%s device_name {opc.lst|-} disp.lst device.inc
"""
import sys
import logging
MAX_STATES = 0x101
def load_opcodes(fname):
"""Load opcodes from .lst file"""
opcodes = []
logging.info("load_opcodes: %s", fname)
try:
f = open(fname, "r")
except Exception, err:
logging.error("cannot read opcodes file %s [%s]", fname, err)
sys.exit(1)
for line in f:
if line.startswith("#"): continue
line = line.rstrip()
if not line: continue
if line.startswith(" ") or line.startswith("\t"):
# append instruction to last opcode
opcodes[-1][1].append(line)
else:
# add new opcode
opcodes.append((line, []))
return opcodes
def load_disp(fname):
logging.info("load_disp: %s", fname)
states = []
try:
f = open(fname, "r")
except Exception, err:
logging.error("cannot read display file %s [%s]", fname, err)
sys.exit(1)
for line in f:
if line.startswith("#"): continue
line = line.strip()
if not line: continue
tokens = line.split()
states += tokens
return states
def emit(f, text):
"""write string to file"""
print >>f, text,
FULL_PROLOG="""\
void %(device)s::%(opcode)s_full()
{
"""
FULL_EPILOG="""\
}
"""
FULL_EAT_ALL="""\
\ticount=0; inst_substate = %(substate)s; return;
"""
FULL_MEMORY="""\
\tif(icount == 0) { inst_substate = %(substate)s; return; }
%(ins)s
\ticount--;
"""
FULL_NONE="""\
%(ins)s
"""
PARTIAL_PROLOG="""\
void %(device)s::%(opcode)s_partial()
{
switch(inst_substate) {
case 0:
"""
PARTIAL_EPILOG="""\
}
\tinst_substate = 0;
}
"""
PARTIAL_EAT_ALL="""\
\ticount=0; inst_substate = %(substate)s; return;
case %(substate)s:;
"""
PARTIAL_MEMORY="""\
\tif(icount == 0) { inst_substate = %(substate)s; return; }
case %(substate)s:
%(ins)s
\ticount--;
"""
PARTIAL_NONE="""\
%(ins)s
"""
def identify_line_type(ins):
if "eat-all-cycles" in ins: return "EAT"
for s in ["read", "write", "prefetch(", "prefetch_noirq("]:
if s in ins:
return "MEMORY"
return "NONE"
def save_opcodes(f, device, opcodes):
for name, instructions in opcodes:
d = { "device": device,
"opcode": name,
}
emit(f, FULL_PROLOG % d)
substate = 1
for ins in instructions:
d["substate"] = str(substate)
d["ins"] = ins
line_type = identify_line_type(ins)
if line_type == "EAT":
emit(f, FULL_EAT_ALL % d)
substate += 1
elif line_type == "MEMORY":
emit(f, FULL_MEMORY % d)
substate += 1
else:
emit(f, FULL_NONE %d)
emit(f, FULL_EPILOG % d)
emit(f, PARTIAL_PROLOG % d)
substate = 1
for ins in instructions:
d["substate"] = str(substate)
d["ins"] = ins
line_type = identify_line_type(ins)
if line_type == "EAT":
emit(f, PARTIAL_EAT_ALL % d)
substate += 1
elif line_type == "MEMORY":
emit(f, PARTIAL_MEMORY % d)
substate += 1
else:
emit(f, PARTIAL_NONE %d)
emit(f, PARTIAL_EPILOG % d)
DO_EXEC_FULL_PROLOG="""\
void %(device)s::do_exec_full()
{
\tswitch(inst_state) {
"""
DO_EXEC_FULL_EPILOG="""\
\t}
}
"""
DO_EXEC_PARTIAL_PROLOG="""\
void %(device)s::do_exec_partial()
{
\tswitch(inst_state) {
"""
DO_EXEC_PARTIAL_EPILOG="""\
\t}
}
"""
DISASM_PROLOG="""\
const %(device)s::disasm_entry %(device)s::disasm_entries[0x100] = {
"""
DISASM_EPILOG="""\
};
"""
def save_tables(f, device, states):
d = { "device": device,
}
assert len(states) == MAX_STATES
emit(f, DO_EXEC_FULL_PROLOG % d)
for n, state in enumerate(states):
if state == ".": continue
if n < MAX_STATES - 1:
emit(f, "\tcase 0x%02x: %s_full(); break;\n" % (n, state))
else:
emit(f, "\tcase %s: %s_full(); break;\n" % ("STATE_RESET", state))
emit(f, DO_EXEC_FULL_EPILOG % d)
emit(f, DO_EXEC_PARTIAL_PROLOG % d)
for n, state in enumerate(states):
if state == ".": continue
if n < MAX_STATES - 1:
emit(f, "\tcase 0x%02x: %s_partial(); break;\n" % (n, state))
else:
emit(f, "\tcase %s: %s_partial(); break;\n" % ("STATE_RESET", state))
emit(f, DO_EXEC_PARTIAL_EPILOG % d)
emit(f, DISASM_PROLOG % d)
for n, state in enumerate(states):
if state == ".": continue
if n == MAX_STATES - 1: break
tokens = state.split("_")
opc = tokens[0]
mode = tokens[-1]
extra = "0"
if opc in ["jsr", "bsr"]:
extra = "DASMFLAG_STEP_OVER"
elif opc in ["rts", "rti", "rtn"]:
extra = "DASMFLAG_STEP_OUT"
emit(f, '\t{ "%s", DASM_%s, %s },\n' % (opc, mode, extra))
emit(f, DISASM_EPILOG % d)
def save(fname, device, opcodes, states):
logging.info("saving: %s", fname)
try:
f = open(fname, "w")
except Exception, err:
logging.error("cannot write file %s [%s]", fname, err)
sys.exit(1)
save_opcodes(f,device, opcodes)
emit(f, "\n")
save_tables(f, device, states)
f.close()
def main(argv):
debug = True
logformat=("%(levelname)s:"
"%(module)s:"
"%(lineno)d:"
"%(threadName)s:"
"%(message)s")
if debug:
logging.basicConfig(level=logging.INFO, format=logformat)
else:
logging.basicConfig(level=logging.WARNING, format=logformat)
if len(argv) != 5:
print USAGE % argv[0]
return 1
device_name = argv[1]
opcodes = []
if argv[2] != "-":
opcodes = load_opcodes(argv[2])
logging.info("found %d opcodes", len(opcodes))
else:
logging.info("skipping opcode reading")
states = load_disp(argv[3])
logging.info("loaded %s states", len(states))
assert len(states) == MAX_STATES
save(argv[4], device_name, opcodes, states)
# ======================================================================
if __name__ == "__main__":
sys.exit(main(sys.argv))

View File

@ -1,959 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdarg.h>
#include <ctype.h>
#include "osdcomm.h"
enum {
I_POST = 0x00000001,
I_REP = 0x00000002,
I_CMODE = 0x00000004,
I_DMODE = 0x00000008,
I_SFAI = 0x00000010,
I_CRM = 0x00000020,
I_DBP = 0x00000040,
I_SFAO = 0x00000080,
I_SFMO = 0x00000100,
I_RND = 0x00000200,
I_MOVM = 0x00000400,
I_SFMA = 0x00000800
};
enum {
T_STD,
T_BRANCH,
T_CBRANCH,
T_IDLE,
T_FLAGS
};
enum { PA, PC, PD, PD24, PI, PML, PMO, PMV, PB, PWA, PWC, PWD, SFAI };
struct instr {
char *name;
char *dasm;
char *run;
int line, cycles, type, baseval, variants;
unsigned int flags;
};
struct pdesc {
const char *opt;
int pcount, id;
};
struct pinf {
const char *start;
int size;
int id;
int pcount;
int ppos[4];
};
static const pdesc pp_r[] = {
{ "a", 0, PA },
{ "c", 0, PC },
{ "d", 0, PD },
{ "d24", 0, PD24 },
{ "i", 0, PI },
{ "ml", 0, PML },
{ "mo", 0, PMO },
{ "mv", 0, PMV },
{ "wa", 1, PWA },
{ "wc", 1, PWC },
{ "wd", 1, PWD },
{ "b", 1, PB },
{ "sfai", 2, SFAI },
{ 0 }
};
static instr cat1[0x40], cat2[0x80], cat3[0x80];
static pinf parse_res[4096];
static int parse_count;
struct vinfo {
unsigned int mask;
int variants;
const char *name;
const char *getter;
};
enum { IxCMODE, IxDMODE, IxSFAI, IxCRM, IxDBP, IxSFAO, IxSFMO, IxRND, IxMOVM, IxSFMA, IxCOUNT };
static const vinfo vinf[] = {
{ I_CMODE, 3, "cmode", "xmode(opcode, 'c')" },
{ I_DMODE, 3, "dmode", "xmode(opcode, 'd')" },
{ I_SFAI, 2, "sfai", "sfai(st1)" },
{ I_CRM, 4, "crm", "crm(st1)" },
{ I_DBP, 2, "dbp", "dbp(st1)" },
{ I_SFAO, 2, "sfao", "sfao(st1)" },
{ I_SFMO, 4, "sfmo", "sfmo(st1)" },
{ I_RND, 8, "rnd", "rnd(st1)" },
{ I_MOVM, 2, "movm", "movm(st1)" },
{ I_SFMA, 4, "sfma", "sfma(st1)" },
{ 0 }
};
static char *xstrdup(const char *str)
{
char *cpy = NULL;
if (str != NULL) {
cpy = (char *)malloc(strlen(str) + 1);
if (cpy != NULL)
strcpy(cpy, str);
}
return cpy;
}
static char *sconcat(char *dest, const char *src)
{
char *r;
int len = strlen(src);
int pos = dest ? strlen(dest) : 0;
r = (char *)realloc(dest, pos+len+2);
memcpy(r + pos, src, len);
r[pos+len] = '\n';
r[pos+len+1] = 0;
return r;
}
static void next(char **q)
{
char *p = *q;
while(*p && *p != ' ')
p++;
while(*p == ' ')
*p++ = 0;
*q = p;
}
static void load(const char *fname)
{
char buf[4096];
FILE *f;
instr *i = 0;
int line = 0;
sprintf(buf, "Error opening %s for reading\n", fname);
f = fopen(fname, "r");
if(!f) {
perror(buf);
exit(1);
}
while(fgets(buf, sizeof(buf), f)) {
char *p = buf;
while(*p && *p != '\r' && *p != '\n')
p++;
*p = 0;
line++;
if(!buf[0]) {
i = 0;
continue;
}
if(buf[0] == ' ' || buf[0] == '\t') {
if(!i) {
fprintf(stderr, "%s:%d: Text line without an instruction.\n", fname, line);
exit(1);
}
if(i->dasm)
i->run = sconcat(i->run, buf);
else {
p = buf;
while(*p == ' ' || *p == '\t')
p++;
i->dasm = xstrdup(p);
}
} else {
char *name=0, *cat=0, *id=0, *cyc=0, *rep=0, *type=0;
p = buf;
int pid, limit;
instr *bi;
unsigned int flags;
name = p;
next(&p);
cat = p;
next(&p);
id = p;
next(&p);
cyc = p;
next(&p);
rep = p;
next(&p);
type = p;
next(&p);
if(*p) {
fprintf(stderr, "%s:%d: Extra text at end of instruction description.\n", fname, line);
exit(1);
}
if(!rep[0]) {
fprintf(stderr, "%s:%d: Missing columns in instruction description.\n", fname, line);
exit(1);
}
flags = 0;
pid = strtol(id, 0, 16);
if(!strcmp(cat, "1")) {
bi = cat1;
limit = 0x40;
} else if(!strcmp(cat, "2a")) {
bi = cat2;
limit = 0x80;
} else if(!strcmp(cat, "2b")) {
bi = cat2;
limit = 0x80;
flags = I_POST;
} else if(!strcmp(cat, "3")) {
bi = cat3;
limit = 0x80;
} else {
fprintf(stderr, "%s:%d: Unknown category '%s'.\n", fname, line, cat);
exit(1);
}
if(pid<0 || pid >= limit) {
fprintf(stderr, "%s:%d: Index %s out of range for category %s.\n", fname, line, id, cat);
exit(1);
}
i = bi + pid;
if(i->name) {
fprintf(stderr, "%s:%d: Conflict with %s instruction line %d.\n", fname, line, i->name, i->line);
exit(1);
}
if(!strcmp(rep, "y"))
flags |= I_REP;
else if(strcmp(rep, "n")) {
fprintf(stderr, "%s:%d: Unknown repetition mode '%s'.\n", fname, line, rep);
exit(1);
}
i->name = xstrdup(name);
i->line = line;
i->cycles = strtol(cyc, 0, 10);
i->flags = flags;
if(type[0] == 0)
i->type = T_STD;
else if(!strcmp(type, "b"))
i->type = T_BRANCH;
else if(!strcmp(type, "cb"))
i->type = T_CBRANCH;
else if(!strcmp(type, "i"))
i->type = T_IDLE;
else if(!strcmp(type, "f"))
i->type = T_FLAGS;
else {
fprintf(stderr, "%s:%d: Unknown type '%s'.\n", fname, line, type);
exit(1);
}
}
}
fclose(f);
}
static void pstr(const char *s, const char *e)
{
parse_res[parse_count].start = s;
parse_res[parse_count].size = e-s;
parse_res[parse_count].id = -1;
parse_res[parse_count].pcount = 0;
parse_count++;
}
static void parse_1(const char *start, const pdesc *inf, const char **str, int emode)
{
const char *p = *str;
const char *s = p;
int depth = 0;
while(*p) {
char c = *p++;
if(!depth && ((c == ',' && emode == ',') || (c == ')' && emode == ')'))) {
if(s != p-1)
pstr(s, p-1);
*str = p;
return;
}
if(c == '(')
depth++;
else if(c == ')') {
depth--;
if(depth < 0) {
if(emode == ',')
fprintf(stderr, "Parse error, missing parameter in '%s'.\n", start);
else
fprintf(stderr, "Parse error, unbalanced parenthesis in '%s'.\n", start);
exit(1);
}
} else if(c == '%' && ((*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9'))) {
char buf[4096];
char *pp = buf;
int i, j;
int pos;
if(s != p-1)
pstr(s, p-1);
while((*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9'))
*pp++ = *p++;
*pp = 0;
for(i=0; inf[i].opt && strcmp(buf, inf[i].opt); i++);
if(!inf[i].opt) {
fprintf(stderr, "Parse error, unhandled parameter %%%s\n", buf);
exit(1);
}
pos = parse_count++;
parse_res[pos].start = 0;
parse_res[pos].size = 0;
parse_res[pos].id = inf[i].id;
parse_res[pos].pcount = inf[i].pcount;
if(inf[i].pcount) {
if(*p != '(') {
fprintf(stderr, "Parse error, missing opening parenthesis on %%%s\n", buf);
exit(1);
} else
p++;
}
*str = p;
for(j=0; j != inf[i].pcount; j++) {
parse_res[pos].ppos[j] = parse_count;
parse_1(start, inf, str, j == inf[i].pcount-1 ? ')' : ',');
}
p = *str;
parse_res[pos].ppos[j] = parse_count;
s = p;
}
}
if(s != p)
pstr(s, p);
*str = p;
switch(emode) {
case 0:
return;
case ',':
fprintf(stderr, "Parse error, missing parameter at end of string in '%s'.\n", start);
exit(1);
case ')':
fprintf(stderr, "Parse error, missing closing parenthesis at end of string in '%s'.\n", start);
exit(1);
}
}
static void parse(const char *str, const pdesc *inf)
{
parse_count = 0;
parse_1(str, inf, &str, 0);
}
static void compute_cache_ids_cat(instr *il, int count, int *baseval)
{
int i, j;
for(i=0; i != count; i++)
if(il[i].run) {
unsigned int flags = il[i].flags;
int variants = 1;
parse(il[i].run, pp_r);
for(j=0; j != parse_count; j++) {
switch(parse_res[j].id) {
case -1: break;
case PA: flags |= I_SFAO; break;
case PC: flags |= I_CMODE|I_CRM; break;
case PD: flags |= I_DMODE|I_DBP; break;
case PI: break;
case PD24: flags |= I_DMODE|I_DBP; break;
case PML: flags |= I_SFMA; break;
case PMO: flags |= I_SFMO|I_RND|I_MOVM; break;
case PMV: flags |= I_SFMO|I_MOVM; break;
case PB: break;
case PWA: break;
case PWC: flags |= I_CMODE; break;
case PWD: flags |= I_DMODE|I_DBP; break;
case SFAI: flags |= I_SFAI; break;
}
}
il[i].flags = flags;
il[i].baseval = *baseval;
for(j=0; vinf[j].mask; j++)
if(flags & vinf[j].mask)
variants *= vinf[j].variants;
il[i].variants = variants;
*baseval += variants;
}
}
static void scp(char **str, int idx)
{
memcpy(*str, parse_res[idx].start, parse_res[idx].size);
(*str) += parse_res[idx].size;
}
static void scs(char **str, const char *s)
{
int len = strlen(s);
memcpy(*str, s, len);
(*str) += len;
}
static void save_dasm_cat(FILE *f, const char *def, instr *il, int count)
{
static const pdesc pp[] = {
{ "c", 0, PC },
{ "d", 0, PD },
{ "i", 0, PI },
{ 0 }
};
int i;
fprintf(f, "#ifdef %s\n", def);
for(i=0; i != count; i++)
if(il[i].name) {
int par[3];
int pc = 0;
int j;
char buf[4096], *p = buf;
parse(il[i].dasm, pp);
for(j=0; j<parse_count;j++) {
switch(parse_res[j].id) {
case -1:
scp(&p, j);
break;
case PC:
scs(&p, "%s");
par[pc++] = PC;
break;
case PD:
scs(&p, "%s");
par[pc++] = PD;
break;
case PI:
scs(&p, "%02x");
par[pc++] = PI;
break;
}
}
*p = 0;
fprintf(f, " case 0x%02x:\n", i);
fprintf(f, " sprintf(buf, \"%s\"", buf);
for(j=0; j != pc; j++)
switch(par[j]) {
case PC:
fprintf(f, ", get_memadr(opcode, 'c')");
break;
case PD:
fprintf(f, ", get_memadr(opcode, 'd')");
break;
case PI:
fprintf(f, ", opcode & 0xff");
break;
}
fprintf(f, ");\n");
fprintf(f, " break;\n");
fprintf(f, "\n");
}
fprintf(f, "#endif\n\n");
}
static void intrp_expand(char **p, int s, int e)
{
int i;
for(i=s; i<e;) {
switch(parse_res[i].id) {
case -1:
scp(p, i);
break;
case PA:
scs(p, "aacc_to_output()");
break;
case PC:
scs(p, "opc_read_c(opcode)");
break;
case PD:
scs(p, "(opc_read_d(opcode) << 8)");
break;
case PI:
scs(p, "(opcode & 0xff)");
break;
case PD24:
scs(p, "opc_read_d(opcode)");
break;
case PML:
scs(p, "macc_to_loop()");
break;
case PMO:
scs(p, "macc_to_output()");
break;
case PMV:
scs(p, "check_macc_overflow()");
break;
case PB:
scs(p, "pc = ");
intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]);
scs(p, ";\n");
scs(p, " sti |= S_BRANCH");
break;
case PWA:
scs(p, "r = ");
intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]);
scs(p, ";\n");
scs(p, " if(r < -0x80000000 || r > 0x7fffffff)\n");
scs(p, " st1 |= ST1_AOV;\n");
scs(p, " aacc = r");
break;
case PWC:
scs(p, "opc_write_c(opcode, ");
intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]);
scs(p, ")");
break;
case PWD:
scs(p, "opc_write_d(opcode, ");
intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]);
scs(p, ")");
break;
case SFAI:
intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]);
scs(p, " = ");
intrp_expand(p, parse_res[i].ppos[1], parse_res[i].ppos[2]);
scs(p, ";\n");
scs(p, " if(st1 & ST1_SFAI)\n");
scs(p, " ");
intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]);
scs(p, " = ((INT32)");
intrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1]);
scs(p, ") >> 1");
break;
}
if(parse_res[i].id == -1)
i++;
else
i = parse_res[i].ppos[parse_res[i].pcount];
}
}
static void save_intrp_cat(FILE *f, const char *def, instr *il, int count, unsigned int fmask, unsigned int fval)
{
int i;
fprintf(f, "#ifdef %s\n", def);
for(i=0; i != count; i++)
if(il[i].run) {
fprintf(f, "case 0x%02x: // %s\n", i, il[i].name);
if((il[i].flags & fmask) == fval) {
char buf[4096], *p = buf;
parse(il[i].run, pp_r);
intrp_expand(&p, 0, parse_count);
*p = 0;
fprintf(f, "%s", buf);
}
fprintf(f, " break;\n\n");
}
fprintf(f, "#endif\n\n");
}
static void save_cdec_cat(FILE *f, const char *def, instr *il, int count, unsigned int fmask, unsigned int fval)
{
int i;
fprintf(f, "#ifdef %s\n", def);
for(i=0; i != count; i++)
if(il[i].run) {
int m=1, j;
unsigned int flags = il[i].flags;
fprintf(f, "case 0x%02x: // %s\n", i, il[i].name);
if((il[i].flags & fmask) == fval) {
fprintf(f, " *op = %d", il[i].baseval);
for(j=0; vinf[j].mask; j++)
if(flags & vinf[j].mask) {
if(m != 1)
fprintf(f, " + %d*%s", m, vinf[j].getter);
else
fprintf(f, " + %s", vinf[j].getter);
m *= vinf[j].variants;
}
fprintf(f, ";\n");
switch(il[i].type) {
case T_FLAGS:
fprintf(f, "%s", il[i].run);
break;
case T_BRANCH:
fprintf(f, " cs->branch = BR_UB;\n");
break;
case T_CBRANCH:
fprintf(f, " cs->branch = BR_CB;\n");
break;
case T_IDLE:
fprintf(f, " cs->branch = BR_IDLE;\n");
break;
}
}
fprintf(f, " break;\n\n");
}
fprintf(f, "#endif\n\n");
}
static void cintrp_expand(char **p, int s, int e, const int *cv)
{
int i;
for(i=s; i<e;) {
switch(parse_res[i].id) {
case -1:
scp(p, i);
break;
case PA:
if(cv[IxSFAO])
scs(p, "(aacc << 7)");
else
scs(p, "aacc");
break;
case PC: {
const char *r = NULL;
if(cv[IxCMODE] == 0)
r = "cmem[i->param]";
else if(cv[IxCMODE] == 1)
r = "cmem[ca]";
else if(cv[IxCMODE] == 2)
r = "cmem[ca++]";
else
abort();
if(cv[IxCRM] == 0 || cv[IxCRM] == 3)
scs(p, r);
else if(cv[IxCRM] == 1) {
scs(p, "(");
scs(p, r);
scs(p, " & 0xffff0000)");
} else if(cv[IxCRM] == 2) {
scs(p, "(");
scs(p, r);
scs(p, " << 16)");
} else
abort();
break;
}
case PD:
if(cv[IxDMODE] == 0)
if(cv[IxDBP])
scs(p, "(dmem1[(i->param + ba1) & 0x1f] << 8)");
else
scs(p, "(dmem0[(i->param + ba0) & 0xff] << 8)");
else if(cv[IxDMODE] == 1)
if(cv[IxDBP])
scs(p, "(dmem1[(id + ba1) & 0x1f] << 8)");
else
scs(p, "(dmem0[(id + ba0) & 0xff] << 8)");
else if(cv[IxDMODE] == 2)
if(cv[IxDBP])
scs(p, "(dmem1[((id++) + ba1) & 0x1f] << 8)");
else
scs(p, "(dmem0[((id++) + ba0) & 0xff] << 8)");
else
abort();
break;
case PI:
scs(p, "i->param");
break;
case PD24:
if(cv[IxDMODE] == 0)
if(cv[IxDBP])
scs(p, "dmem1[(i->param + ba1) & 0x1f]");
else
scs(p, "dmem0[(i->param + ba0) & 0xff]");
else if(cv[IxDMODE] == 1)
if(cv[IxDBP])
scs(p, "dmem1[(id + ba1) & 0x1f]");
else
scs(p, "dmem0[(id + ba0) & 0xff]");
else if(cv[IxDMODE] == 2)
if(cv[IxDBP])
scs(p, "dmem1[((id++) + ba1) & 0x1f]");
else
scs(p, "dmem0[((id++) + ba0) & 0xff]");
else
abort();
break;
case PML:
if(cv[IxSFMA] == 0)
scs(p, "macc");
else if(cv[IxSFMA] == 1)
scs(p, "(macc << 2)");
else if(cv[IxSFMA] == 2)
scs(p, "(macc << 4)");
else if(cv[IxSFMA] == 3)
scs(p, "(macc >> 16)");
else
abort();
break;
case PMO: {
static const long long rounding[8] = {
0,
1LL << (48-32-1),
1LL << (48-24-1),
1LL << (48-30-1),
1LL << (48-16-1),
0, 0, 0
};
static const unsigned long long rmask[8] = {
~0ULL,
(~0ULL) << (48-32),
(~0ULL) << (48-24),
(~0ULL) << (48-30),
(~0ULL) << (48-16),
~0ULL, ~0ULL, ~0ULL
};
char r[256];
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]]);
scs(p, r);
break;
}
case PMV: {
char r[256];
sprintf(r, "check_macc_overflow_%d%s()", cv[IxSFMO], cv[IxMOVM] ? "s" : "");
scs(p, r);
break;
}
case PB:
scs(p, "pc = ");
cintrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1], cv);
scs(p, ";\n");
scs(p, " sti |= S_BRANCH");
break;
case PWA:
scs(p, "r = ");
cintrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1], cv);
scs(p, ";\n");
scs(p, " if(r < -0x80000000 || r > 0x7fffffff)\n");
scs(p, " st1 |= ST1_AOV;\n");
scs(p, " aacc = r");
break;
case PWC:
if(cv[IxCMODE] == 0)
scs(p, "cmem[i->param] = ");
else if(cv[IxCMODE] == 1)
scs(p, "cmem[ca] = ");
else if(cv[IxCMODE] == 2)
scs(p, "cmem[ca++] = ");
else
abort();
cintrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1], cv);
break;
case PWD:
if(cv[IxDMODE] == 0)
if(cv[IxDBP])
scs(p, "dmem1[(i->param + ba1) & 0x1f] = ");
else
scs(p, "dmem0[(i->param + ba0) & 0xff] = ");
else if(cv[IxDMODE] == 1)
if(cv[IxDBP])
scs(p, "dmem1[(id + ba1) & 0x1f] = ");
else
scs(p, "dmem0[(id + ba0) & 0xff] = ");
else if(cv[IxDMODE] == 2)
if(cv[IxDBP])
scs(p, "dmem1[((id++) + ba1) & 0x1f] = ");
else
scs(p, "dmem0[((id++) + ba0) & 0xff] = ");
else
abort();
cintrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1], cv);
break;
case SFAI:
cintrp_expand(p, parse_res[i].ppos[0], parse_res[i].ppos[1], cv);
scs(p, " = ");
if(cv[IxSFAI])
scs(p, "((INT32)(");
cintrp_expand(p, parse_res[i].ppos[1], parse_res[i].ppos[2], cv);
if(cv[IxSFAI])
scs(p, ")) >> 1");
break;
}
if(parse_res[i].id == -1)
i++;
else
i = parse_res[i].ppos[parse_res[i].pcount];
}
}
static void save_cintrp_cat(FILE *f, instr *il, int count)
{
int i;
for(i=0; i != count; i++)
if(il[i].run) {
int cv[IxCOUNT];
int j, k = 0;
unsigned int flags = il[i].flags;
char buf[16384];
memset(cv, 0, sizeof(cv));
parse(il[i].run, pp_r);
for(j=0; j != il[i].variants; j++) {
char *p = buf;
fprintf(f, "case %d: // %s", il[i].baseval + j, il[i].name);
for(k=0; k != IxCOUNT; k++)
if(flags & vinf[k].mask)
fprintf(f, " %s=%d", vinf[k].name, cv[k]);
fprintf(f, "\n");
cintrp_expand(&p, 0, parse_count, cv);
*p = 0;
fprintf(f, "%s", buf);
fprintf(f, " break;\n\n");
for(k=0; k != IxCOUNT; k++)
if(flags & vinf[k].mask) {
cv[k]++;
if(cv[k] != vinf[k].variants)
break;
cv[k] = 0;
}
}
assert(k == IxCOUNT);
}
}
static void compute_cache_ids(void)
{
int baseval = 1;
compute_cache_ids_cat(cat1, 0x40, &baseval);
compute_cache_ids_cat(cat2, 0x80, &baseval);
compute_cache_ids_cat(cat3, 0x80, &baseval);
}
static void save_dasm(FILE *f)
{
save_dasm_cat(f, "DASM1", cat1, 0x40);
save_dasm_cat(f, "DASM2", cat2, 0x80);
save_dasm_cat(f, "DASM3", cat3, 0x80);
}
void save_intrp(FILE *f)
{
save_intrp_cat(f, "INTRP1", cat1, 0x40, 0, 0);
save_intrp_cat(f, "INTRP2A", cat2, 0x80, I_POST, 0);
save_intrp_cat(f, "INTRP2B", cat2, 0x80, I_POST, I_POST);
save_intrp_cat(f, "INTRP3", cat3, 0x80, 0, 0);
}
static void save_cdec(FILE *f)
{
save_cdec_cat(f, "CDEC1", cat1, 0x40, 0, 0);
save_cdec_cat(f, "CDEC2A", cat2, 0x80, I_POST, 0);
save_cdec_cat(f, "CDEC2B", cat2, 0x80, I_POST, I_POST);
save_cdec_cat(f, "CDEC3", cat3, 0x80, 0, 0);
}
static void save_cintrp(FILE *f)
{
fprintf(f, "#ifdef CINTRP\n");
save_cintrp_cat(f, cat1, 0x40);
save_cintrp_cat(f, cat2, 0x80);
save_cintrp_cat(f, cat3, 0x80);
fprintf(f, "#endif\n");
}
static void save(const char *fname)
{
char buf[4096];
FILE *f;
sprintf(buf, "Error opening %s for writing\n", fname);
f = fopen(fname, "w");
if(!f) {
perror(buf);
exit(1);
}
compute_cache_ids();
save_dasm(f);
// save_intrp(f);
save_cdec(f);
save_cintrp(f);
fclose(f);
}
static void clear_cat(instr *il, int count)
{
int i;
for(i=0; i != count; i++) {
free(il[i].name);
free(il[i].dasm);
free(il[i].run);
}
}
static void clear(void)
{
clear_cat(cat1, 0x40);
clear_cat(cat2, 0x80);
clear_cat(cat3, 0x80);
}
int main(int argc, char *argv[])
{
if(argc != 3) {
fprintf(stderr, "Usage:\n%s tmsinstr.lst tms57002.inc\n", argv[0]);
exit(1);
}
memset(cat1, 0, sizeof(cat1));
memset(cat2, 0, sizeof(cat2));
memset(cat3, 0, sizeof(cat3));
load(argv[1]);
save(argv[2]);
clear();
return 0;
}

428
src/emu/cpu/tms57002/tmsmake.py Normal file → Executable file
View File

@ -0,0 +1,428 @@
#!/usr/bin/python
import sys
import re
DASM_ARGS = {
"c": ("%s", "get_memadr(opcode, 'c')"),
"d": ("%s", "get_memadr(opcode, 'd')"),
"i": ("%02x", "opcode & 0xff"),
}
TYPES = {
"": None,
"d": None,
"b": " cs->branch = BR_UB;",
"cb": " cs->branch = BR_CB;",
"i": " cs->branch = BR_IDLE;",
"f": None,
}
def expand_c(v):
fmt = ["%s", "(%s & 0xffff0000)", "(%s << 16)", "%s"][v["crm"]]
param = ["cmem[i->param]", "cmem[ca]", "cmem[ca++]"][v["cmode"]]
return fmt % param
def expand_d(v):
index = ["(i->param + ", "(id + ", "((id++) + "][v["dmode"]]
mask = ["ba0) & 0xff] << 8)", "ba1) & 0x1f] << 8)"][v["dbp"]]
return "(dmem%d[" % v["dbp"] + index + mask
def expand_d24(v):
index = ["(i->param + ", "(id + ", "((id++) + "][v["dmode"]]
mask = ["ba0) & 0xff]", "ba1) & 0x1f]"][v["dbp"]]
return "dmem%d[" % v["dbp"] + index + mask
EXPAND_ML = ["macc", "(macc << 2)", "(macc << 4)", "(macc >> 16)" ]
def expand_mv(v):
c = ["", "s"][v["movm"]]
return "check_macc_overflow_%d%s()" % (v["sfmo"], c)
EXPAND_WC = ["cmem[i->param] =", "cmem[ca] =", "cmem[ca++] ="]
ROUNDING = [ 0, 1 << (48-32-1), 1 << (48-24-1), 1 << (48-30-1),
1 << (48-16-1), 0, 0, 0]
A = (1 << 64) - 1
RMASK= [A,
A - (1 << (48-32)) + 1,
A - (1 << (48-24)) + 1,
A - (1 << (48-30)) + 1,
A - (1 << (48-16)) + 1,
A,
A,
A,
]
def expand_mo(v):
c = ["", "s"][v["movm"]]
return "macc_to_output_%d%s(0x%016xULL, 0x%016xULL)" % (
v["sfmo"], c, ROUNDING[v["rnd"]], RMASK[v["rnd"]])
def expand_wd1(v):
index = ["(i->param + ", "(id + ", "((id++) + "][v["dmode"]]
mask = ["ba0) & 0xff] =", "ba1) & 0x1f] ="][v["dbp"]]
return "dmem%d[" % v["dbp"] + index + mask
WA2 = (
" if(r < -0x80000000 || r > 0x7fffffff)\n"
" st1 |= ST1_AOV;\n"
" aacc = r;")
PDESC_EXPAND = {
"a": lambda v: ["aacc", "(aacc << 7)"][v["sfao"]],
"c": expand_c,
"d": expand_d,
"d24": expand_d24,
"i": lambda v: "i->param",
"ml": lambda v: EXPAND_ML[v["sfma"]],
"mo": expand_mo,
"mv": expand_mv,
"wa1": lambda v: "r =",
"wa2": lambda v: WA2,
"wc1": lambda v: EXPAND_WC[v["cmode"]],
"wd1": expand_wd1,
"b1": lambda v: "pc = ",
"b2": lambda v: " sti |= S_BRANCH;",
"sfai1": lambda v: ["", "((INT32)("][v["sfai"]],
"sfai2": lambda v: ["", ")) >> 1"][v["sfai"]],
}
PDESC = {
"a": (0, ["sfao"]),
"c": (0, ["cmode", "crm"]),
"d": (0, ["dmode", "dbp"]),
"d24": (0, ["dmode", "dbp"]),
"i": (0, []),
"ml": (0, ["sfma"]),
"mo": (0, ["sfmo", "rnd", "movm"]),
"mv": (0, ["sfmo", "movm"]),
"wa": (1, []),
"wc": (1, ["cmode"]),
"wd": (1, ["dmode", "dbp"]),
"b": (1, []),
"sfai": (2, ["sfai"]),
}
VARIANTS = {
"cmode": (3, "xmode(opcode, 'c')" ),
"dmode": (3, "xmode(opcode, 'd')" ),
"sfai": (2, "sfai(st1)"),
"crm": (4, "crm(st1)"),
"dbp": (2, "dbp(st1)"),
"sfao": (2, "sfao(st1)"),
"sfmo": (4, "sfmo(st1)"),
"rnd": (8, "rnd(st1)"),
"movm": (2, "movm(st1)"),
"sfma": (4, "sfma(st1)"),
# dummy
"post": (1, None),
}
VARIANT_CANONICAL_ORDER = [
"cmode",
"dmode",
"sfai",
"crm",
"dbp",
"sfao",
"sfmo",
"rnd",
"movm",
"sfma",
]
def EmitWithPrefix(f, out, prefix):
for o in out:
print >>f, prefix + o
class Instruction:
def __init__(self, line):
token = line.split()
if len(token) == 5:
token.append("")
assert len(token) == 6
self._name = token[0]
self._cat = token[1]
self._id = int(token[2], 16)
self._cyc = int(token[3])
self._rep = token[4]
self._type = token[5]
self._flags = set()
if self._cat == "2b":
self._flags.add("post")
self._dasm = None
self._run = []
self._variants = 1
# sanity checks
assert 0 <= self._id
if self._cat == "1":
assert self._id < 0x40
else:
assert self._id < 0x80
assert self._type in TYPES
def __str__(self):
return repr([self._name, self._cat, self._id, self._variants, self._flags])
def GetDasmInfo(self):
lst = []
def extract(match):
s = match.group()[1:]
assert s in DASM_ARGS
fmt, val = DASM_ARGS[s]
lst.append(val)
return fmt
s = re.sub("%.", extract, self._dasm)
return s, lst
def GetCdecSum(self):
lst = []
n = 1
for f in VARIANT_CANONICAL_ORDER:
if f in self._flags:
c, s = VARIANTS[f]
lst.append(" + ")
if n != 1:
lst.append("%d*" % n)
lst.append(s)
n *=c
return "".join(lst)
def EmitDasm(self, f, prefix):
opcode, args = self.GetDasmInfo()
args = [", " + a for a in args]
print >>f, "%scase 0x%02x:" % (prefix, self._id)
print >>f, "%s sprintf(buf, \"%s\"%s);" % (prefix, opcode, "".join(args))
print >>f, "%s break;" % prefix
def EmitCdec(self, f, prefix, no, empty):
print >>f, "%scase 0x%02x: // %s" % (prefix, self._id, self._name)
if not empty:
print >>f, "%s *op = %s%s;" % (prefix, no, self.GetCdecSum())
if self._type == "f":
for l in self._run:
print >>f, prefix + l
else:
l = TYPES[self._type]
if l:
print >>f, prefix + l
print >>f, "%s break;" % prefix
def ExpandCintrp(self, line, values):
def extract(match):
s = match.group()[1:]
assert s in PDESC_EXPAND
# call the right expand_XXX function
return PDESC_EXPAND[s](values)
return re.sub("%[a-z0-9]+", extract, line)
def PreprocessRunString(self):
out = []
for r in self._run:
if "%wa(" in r:
assert r.endswith(");")
r = r[0:-2].replace("%wa(", "%wa1 ") + ";"
out.append(r)
out.append("%wa2")
elif "%wd(" in r:
assert r.endswith(");")
r = r[0:-2].replace("%wd(", "%wd1 ") + ";"
out.append(r)
elif "%wc(" in r:
assert r.endswith(");")
r = r[0:-2].replace("%wc(", "%wc1 ") + ";"
out.append(r)
elif "%b(" in r:
assert r.endswith(");")
r = r[0:-2].replace("%b(", "%b1") + ";"
out.append(r)
out.append("%b2")
elif "%sfai(" in r:
assert r.endswith(");")
r = r[0:-2].replace("%sfai(", "")
r = r.replace(",", " = %sfai1", 1)
out.append(r + "%sfai2;")
else:
out.append(r)
return out
def EmitCintrpRecurse(self, f, prefix, no, flags_fixed, flags_unfixed):
if not flags_unfixed:
vals = []
for v in VARIANT_CANONICAL_ORDER:
if v in flags_fixed:
#print "@@@@", f
vals.append("%s=%d" % (v, flags_fixed[v]))
out = []
out.append("case %d: // %s %s" % (no, self._name, " ".join(vals)))
for line in self.PreprocessRunString():
out.append(self.ExpandCintrp(line, flags_fixed))
out.append(" break;")
out.append("")
EmitWithPrefix(f, out, prefix)
return no + 1
x = flags_unfixed.pop(-1)
n = VARIANTS[x][0]
for i in range(n):
flags_fixed[x] = i
no = self.EmitCintrpRecurse(f, prefix, no, flags_fixed, flags_unfixed)
flags_unfixed.append(x)
return no
def EmitCintrp(self, f, prefix, no):
if not self._run:
return no
flags = [fn for fn in VARIANT_CANONICAL_ORDER
if fn in self._flags]
return self.EmitCintrpRecurse(f, prefix, no, {}, flags)
def Finalize(self):
def extract(match):
s = match.group()[1:]
assert s in PDESC
self._flags.update(PDESC[s][1])
# result does not matter
return "X"
for line in self._run:
# ignore result of substitution
re.sub("%[a-z0-9]+", extract, line)
for f in self._flags:
self._variants *= VARIANTS[f][0]
def AddInfo(self, line):
if self._dasm is None:
self._dasm = line.lstrip()
else:
self._run.append(line)
def ins_cmp_dasm(a, b):
if a._cat[0] != b._cat[0]:
return cmp(a._cat[0], b._cat[0])
else:
return cmp(a._id, b._id)
def LoadLst(filename):
instructions = []
ins = None
for n, line in enumerate(open(filename)):
line = line.rstrip()
if not line and ins:
# new lines separate intructions
ins.Finalize()
ins = None
elif line[0] in [" ", "\t"]:
assert ins
ins.AddInfo(line)
else:
ins = Instruction(line)
instructions.append(ins)
if ins:
ins.Finalize()
return instructions
def EmitDasm(f, ins_list):
ins_list.sort(cmp=ins_cmp_dasm)
last_cat = ""
for i in ins_list:
cat = i._cat[0]
if cat != last_cat:
if last_cat:
print >>f, "#endif"
print >>f
print >>f, "#ifdef DASM" + cat
last_cat = cat
i.EmitDasm(f, " ")
print >>f
print >>f, "#endif"
print >>f
def EmitCdec(f, ins_list):
ins_list.sort(cmp=ins_cmp_dasm)
no = 1
last_cat = ""
for i in ins_list:
if not i._run: continue
cat = i._cat.upper()
if cat == "2B": cat = "2A"
if cat == "3": continue
if cat != last_cat:
if last_cat:
print >>f, "#endif"
print >>f
print >>f, "#ifdef CDEC" + cat
last_cat = cat
i.EmitCdec(f, "", no, i._cat == "2b")
no += i._variants
print >>f
no = 1
for i in ins_list:
if not i._run: continue
cat = i._cat.upper()
if cat == "2A": cat = "2B"
if cat == "1":
no += i._variants
continue
if cat != last_cat:
if last_cat:
print >>f, "#endif"
print >>f
print >>f, "#ifdef CDEC" + cat
last_cat = cat
i.EmitCdec(f, "", no, i._cat == "2a")
no += i._variants
print >>f
print >>f, "#endif"
print >>f
def EmitCintrp(f, ins_list):
ins_list.sort(cmp=ins_cmp_dasm)
print >>f, "#ifdef CINTRP"
no = 1
for i in ins_list:
no = i.EmitCintrp(f, "", no)
print >>f, "#endif"
ins_list = LoadLst(sys.argv[1])
try:
f = open(sys.argv[2], "w")
except Exception, err:
logging.error("cannot write file %s [%s]", fname, err)
sys.exit(1)
EmitDasm(f, ins_list)
EmitCdec(f, ins_list)
EmitCintrp(f, ins_list)