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()