mirror of
https://github.com/holub/mame
synced 2025-04-23 08:49:55 +03:00
m6502,tms57002: Snakes in an emulator [Robert Muth, O. Galibert]
This commit is contained in:
parent
b4d0dde34a
commit
627ac29a1a
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -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
|
||||
|
@ -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 $@
|
||||
|
||||
|
||||
#-------------------------------------------------
|
||||
|
@ -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
273
src/emu/cpu/m6502/m6502make.py
Normal file → Executable 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))
|
||||
|
@ -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
428
src/emu/cpu/tms57002/tmsmake.py
Normal file → Executable 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)
|
Loading…
Reference in New Issue
Block a user