305 lines
11 KiB
Lua
Executable File
305 lines
11 KiB
Lua
Executable File
local patternInstruction="(E?)%s*(%d*)%s*([a-z_0-9]+)%s*(.*)"
|
|
local patternDecoderRule="(E?)%s*([a-z_0-9]+)%s+(-?%d[ds]?)"
|
|
|
|
local opcodeFile="opcode.list"
|
|
local decoderRuleFile="decoder.list"
|
|
|
|
local defineFile="../common/opcodeList.h"
|
|
local decoderSourceFile="../interpreter/decoder.c"
|
|
local decoderHeaderFile="../interpreter/decoder.h"
|
|
local decoderImpHeaderFile="../interpreter/decoderImp.h"
|
|
local executerSourceFile="../interpreter/executer.c"
|
|
local executerHeaderFile="../interpreter/executer.h"
|
|
local executerImpHeaderFile="../interpreter/executerImp.h"
|
|
local opcodeListSourceFile="../common/opcodeList.c"
|
|
|
|
-- first, parse instruction file
|
|
|
|
local instructions={}
|
|
local maxNameLen, maxDescLen=0, 0
|
|
|
|
local function readInstruction(line)
|
|
local extended, code, mnemonic, desc=line:match(patternInstruction)
|
|
local instruction={
|
|
extended=extended~='',
|
|
code=code~='' and tonumber(code) or nil,
|
|
mnemonic=mnemonic,
|
|
desc=#desc~=0 and desc or '[No description]'
|
|
}
|
|
if #instruction.mnemonic>maxNameLen then
|
|
maxNameLen=#instruction.mnemonic
|
|
end
|
|
if #instruction.desc>maxDescLen then
|
|
maxDescLen=#instruction.desc
|
|
end
|
|
table.insert(instructions, instruction)
|
|
return instruction
|
|
end
|
|
|
|
for line in io.lines(opcodeFile) do
|
|
if not (#line==0 or line:sub(1,1)=='#') then
|
|
readInstruction(line)
|
|
end
|
|
end
|
|
|
|
print("Total instruction count: "..#instructions)
|
|
|
|
-- second, parse decoder rules
|
|
|
|
local byRule={}
|
|
|
|
local function readDecoderRule(line)
|
|
local extended, mnemonic, rule=line:match(patternDecoderRule)
|
|
extended=extended~=''
|
|
local found=false
|
|
for i, instruction in ipairs(instructions) do
|
|
if instruction.mnemonic==mnemonic and instruction.extended==extended then
|
|
found=true
|
|
instruction.rule=rule
|
|
if not byRule[rule] then
|
|
byRule[rule]={}
|
|
end
|
|
table.insert(byRule[rule], instruction)
|
|
end
|
|
end
|
|
if not found then
|
|
error("Found rule for nonexistent instruction "..mnemonic)
|
|
end
|
|
end
|
|
|
|
for line in io.lines(decoderRuleFile) do
|
|
if not (#line==0 or line:sub(1,1)=='#') then
|
|
readDecoderRule(line)
|
|
end
|
|
end
|
|
|
|
for i, instruction in ipairs(instructions) do
|
|
if not instruction.rule then
|
|
error("Instruction "..instruction.mnemonic.." doesn't have a decoder rule")
|
|
end
|
|
end
|
|
|
|
-- now, let's assign them numbers
|
|
|
|
local normal={}
|
|
local extended={}
|
|
|
|
local function addInstruction(instruction, list, len)
|
|
if instruction.code then
|
|
list[instruction.code+1]=instruction
|
|
return instruction.code
|
|
end
|
|
local i
|
|
for i=1, len do
|
|
if not list[i] then
|
|
list[i]=instruction
|
|
instruction.code=i-1
|
|
return i-1
|
|
end
|
|
end
|
|
error("Not enough space in list to fit instruction "..instruction.mnemonic)
|
|
end
|
|
|
|
for k, instruction in ipairs(instructions) do
|
|
if instruction.extended then
|
|
addInstruction(instruction, extended, 256)
|
|
else
|
|
addInstruction(instruction, normal, 64)
|
|
end
|
|
end
|
|
|
|
-- now, let's write these goddamn files
|
|
|
|
defineFile=io.open(defineFile, "w+")
|
|
defineFile:write("#ifndef OPCODE_LIST\n#define OPCODE_LIST\n\n")
|
|
defineFile:write("void Opcode_registerOpcodes();\n\n")
|
|
local count, extendedCount=0, 0
|
|
for i=1, 64 do
|
|
local instruction=normal[i]
|
|
if instruction then
|
|
count=count+1
|
|
defineFile:write("#define OP_"..instruction.mnemonic.." "..instruction.code.."\n")
|
|
end
|
|
end
|
|
for i=1, 256 do
|
|
local instruction=extended[i]
|
|
if instruction then
|
|
extendedCount=extendedCount+1
|
|
defineFile:write("#define OP_E_"..instruction.mnemonic.." "..instruction.code.."\n")
|
|
end
|
|
end
|
|
defineFile:write("\n")
|
|
defineFile:write("#define OPCODE_COUNT "..count.."\n")
|
|
defineFile:write("#define OPCODE_EXT_COUNT "..extendedCount.."\n")
|
|
defineFile:write("#define OPCODE_NAME_LEN "..(maxNameLen+1).."\n")
|
|
defineFile:write("#define OPCODE_DESC_LEN "..(maxDescLen+1).."\n")
|
|
defineFile:write("\n#endif\n")
|
|
defineFile:close()
|
|
|
|
executerSourceFile=io.open(executerSourceFile, "w+")
|
|
executerSourceFile:write("#include \"executer.h\"\n\n")
|
|
executerSourceFile:write("void Proc_executeInstruction(proc_t *proc, opcode_data_t *instruction) {\n")
|
|
executerSourceFile:write("\tif(instruction->ext) {\n")
|
|
executerSourceFile:write("\t\tswitch(instruction->op) {\n")
|
|
for i=1, 256 do
|
|
local instruction=extended[i]
|
|
if instruction then
|
|
executerSourceFile:write("\t\t\tcase OP_E_"..instruction.mnemonic..":\n")
|
|
executerSourceFile:write("\t\t\t\tinstructionExt_"..instruction.mnemonic.."(proc, instruction);\n")
|
|
executerSourceFile:write("\t\t\t\tbreak;\n")
|
|
end
|
|
end
|
|
executerSourceFile:write("\t\t\tdefault:\n")
|
|
executerSourceFile:write("\t\t\t\tillegalInstruction(proc, instruction);\n")
|
|
executerSourceFile:write("\t\t}\n")
|
|
executerSourceFile:write("\t} else {\n")
|
|
executerSourceFile:write("\t\tswitch(instruction->op) {\n")
|
|
for i=1, 64 do
|
|
local instruction=normal[i]
|
|
if instruction then
|
|
executerSourceFile:write("\t\t\tcase OP_"..instruction.mnemonic..":\n")
|
|
executerSourceFile:write("\t\t\t\tinstruction_"..instruction.mnemonic.."(proc, instruction);\n")
|
|
executerSourceFile:write("\t\t\t\tbreak;\n")
|
|
end
|
|
end
|
|
executerSourceFile:write("\t\t\tdefault:\n")
|
|
executerSourceFile:write("\t\t\t\tillegalInstruction(proc, instruction);\n")
|
|
executerSourceFile:write("\t\t}\n")
|
|
executerSourceFile:write("\t}\n")
|
|
executerSourceFile:write("}\n")
|
|
executerSourceFile:close()
|
|
|
|
executerHeaderFile=io.open(executerHeaderFile, "w+")
|
|
executerHeaderFile:write("#ifndef EXECUTER_H\n")
|
|
executerHeaderFile:write("#define EXECUTER_H\n\n")
|
|
executerHeaderFile:write("#include \"../common/opcode.h\"\n")
|
|
executerHeaderFile:write("#include \"proc.h\"\n")
|
|
executerHeaderFile:write("#include \"executerImp.h\"\n\n")
|
|
executerHeaderFile:write("void Proc_executeInstruction(proc_t *proc, opcode_data_t *instruction);\n\n")
|
|
executerHeaderFile:write("#endif\n")
|
|
executerHeaderFile:close()
|
|
|
|
executerImpHeaderFile=io.open(executerImpHeaderFile, "w+")
|
|
executerImpHeaderFile:write("#ifndef EXECUTER_IMP_H\n")
|
|
executerImpHeaderFile:write("#define EXECUTER_IMP_H\n\n")
|
|
executerImpHeaderFile:write("#include \"proc.h\"\n")
|
|
executerImpHeaderFile:write("#include \"../common/opcode.h\"\n\n")
|
|
for i=1, 64 do
|
|
local instruction=normal[i]
|
|
if instruction then
|
|
executerImpHeaderFile:write("void instruction_"..instruction.mnemonic.."(proc_t *proc, opcode_data_t *instruction);\n")
|
|
end
|
|
end
|
|
executerImpHeaderFile:write("\n")
|
|
for i=1, 256 do
|
|
local instruction=extended[i]
|
|
if instruction then
|
|
executerImpHeaderFile:write("void instructionExt_"..instruction.mnemonic.."(proc_t *proc, opcode_data_t *instruction);\n")
|
|
end
|
|
end
|
|
executerImpHeaderFile:write("\n")
|
|
executerImpHeaderFile:write("void illegalInstruction(proc_t *proc, opcode_data_t *instruction);\n\n")
|
|
executerImpHeaderFile:write("#endif\n")
|
|
executerImpHeaderFile:close()
|
|
|
|
decoderSourceFile=io.open(decoderSourceFile, "w+")
|
|
decoderSourceFile:write("#include \"decoder.h\"\n")
|
|
decoderSourceFile:write("#include \"decoderImp.h\"\n\n")
|
|
decoderSourceFile:write("void Proc_decodeInstruction(proc_t *proc, opcode_t *op, opcode_data_t *instruction) {\n")
|
|
decoderSourceFile:write("\tinstruction->op=op->op;\n")
|
|
decoderSourceFile:write("\tinstruction->nArgs=op->nArgs;\n")
|
|
decoderSourceFile:write("\tinstruction->ext=0;\n")
|
|
decoderSourceFile:write("\tswitch(op->op) {\n")
|
|
for rule, list in pairs(byRule) do
|
|
local found=false
|
|
if rule:sub(1,1)~='-' then
|
|
for i, instruction in ipairs(list) do
|
|
if not instruction.extended then
|
|
decoderSourceFile:write("\t\tcase OP_"..instruction.mnemonic..":\n")
|
|
found=true
|
|
end
|
|
end
|
|
if found then
|
|
decoderSourceFile:write("\t\t\t// rule is "..rule.."\n")
|
|
decoderSourceFile:write("\t\t\tdecodeInstructionImp(proc, op, instruction, RULE_"..rule..");\n")
|
|
decoderSourceFile:write("\t\t\tbreak;\n")
|
|
end
|
|
end
|
|
end
|
|
decoderSourceFile:write("\t}\n")
|
|
decoderSourceFile:write("}\n\n")
|
|
decoderSourceFile:write("void Proc_decodeInstructionExt(proc_t *proc, opcode_ext_t *op, opcode_data_t *instruction) {\n")
|
|
decoderSourceFile:write("\tinstruction->op=op->op;\n")
|
|
decoderSourceFile:write("\tinstruction->nArgs=op->nArgs;\n")
|
|
decoderSourceFile:write("\tinstruction->ext=1;\n")
|
|
decoderSourceFile:write("\tswitch(op->op) {\n")
|
|
for rule, list in pairs(byRule) do
|
|
if rule:sub(1,1)~='-' then
|
|
local found=false
|
|
for i, instruction in ipairs(list) do
|
|
if instruction.extended then
|
|
decoderSourceFile:write("\t\tcase OP_E_"..instruction.mnemonic..":\n")
|
|
found=true
|
|
end
|
|
end
|
|
if found then
|
|
decoderSourceFile:write("\t\t\t// rule is "..rule.."\n")
|
|
decoderSourceFile:write("\t\t\tdecodeInstructionExtImp(proc, op, instruction, RULE_"..rule..");\n")
|
|
decoderSourceFile:write("\t\t\tbreak;\n")
|
|
end
|
|
end
|
|
end
|
|
decoderSourceFile:write("\t}\n")
|
|
decoderSourceFile:write("}\n")
|
|
decoderSourceFile:close()
|
|
|
|
decoderHeaderFile=io.open(decoderHeaderFile, "w+")
|
|
decoderHeaderFile:write("#ifndef DECODER_H\n")
|
|
decoderHeaderFile:write("#define DECODER_H\n\n")
|
|
decoderHeaderFile:write("#include \"proc.h\"\n")
|
|
decoderHeaderFile:write("#include \"../common/opcode.h\"\n\n")
|
|
decoderHeaderFile:write("void Proc_decodeInstruction(proc_t *proc, opcode_t *op, opcode_data_t *instruction);\n")
|
|
decoderHeaderFile:write("void Proc_decodeInstructionExt(proc_t *proc, opcode_ext_t *op, opcode_data_t *instruction);\n\n")
|
|
decoderHeaderFile:write("\n")
|
|
decoderHeaderFile:write("#endif\n")
|
|
decoderHeaderFile:close()
|
|
|
|
decoderImpHeaderFile=io.open(decoderImpHeaderFile, "w+")
|
|
decoderImpHeaderFile:write("#ifndef DECODER_IMP_H\n")
|
|
decoderImpHeaderFile:write("#define DECODER_IMP_H\n\n")
|
|
decoderImpHeaderFile:write("#include \"proc.h\"\n")
|
|
decoderImpHeaderFile:write("#include \"../common/opcode.h\"\n\n")
|
|
decoderImpHeaderFile:write("#include \"stack.h\"\n\n")
|
|
decoderImpHeaderFile:write("void decodeInstructionImp(proc_t *proc, opcode_t *op, opcode_data_t *instruction, char mode);\n")
|
|
decoderImpHeaderFile:write("void decodeInstructionExtImp(proc_t *proc, opcode_ext_t *op, opcode_data_t *instruction, char mode);\n\n")
|
|
local i=0
|
|
for rule in pairs(byRule) do
|
|
if rule:sub(1,1)~='-' then
|
|
decoderImpHeaderFile:write("#define RULE_"..rule.." "..i.."\n")
|
|
i=i+1
|
|
end
|
|
end
|
|
decoderImpHeaderFile:write("\n")
|
|
decoderImpHeaderFile:write("#endif\n")
|
|
decoderImpHeaderFile:close()
|
|
|
|
opcodeListSourceFile=io.open(opcodeListSourceFile, "w+")
|
|
opcodeListSourceFile:write("#include \"opcodeList.h\"\n")
|
|
opcodeListSourceFile:write("#include \"opcodeInfo.h\"\n\n")
|
|
opcodeListSourceFile:write("void Opcode_registerOpcodes() {\n")
|
|
opcodeListSourceFile:write("\tOpcode_init();\n")
|
|
for i=1, 64 do
|
|
local instruction=normal[i]
|
|
if instruction then
|
|
opcodeListSourceFile:write("\tOpcode_register(OP_"..instruction.mnemonic..", \""..instruction.mnemonic.."\", OPCODE_TYPE_NORMAL, \""..instruction.desc.."\");\n")
|
|
end
|
|
end
|
|
for i=1, 256 do
|
|
local instruction=extended[i]
|
|
if instruction then
|
|
opcodeListSourceFile:write("\tOpcode_register(OP_E_"..instruction.mnemonic..", \""..instruction.mnemonic.."\", OPCODE_TYPE_EXT, \""..instruction.desc.."\");\n")
|
|
end
|
|
end
|
|
opcodeListSourceFile:write("}\n")
|
|
opcodeListSourceFile:close()
|