{ Copyright (c) 2020 by Nikolay Nikolov Convert z80ins.dat to a set of .inc files for usage with the Free pascal compiler See the file COPYING.FPC, included in this distribution, for details about the copyright. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **********************************************************************} program mkz80ins; {$mode objfpc}{$H+} uses SysUtils,StrUtils; const Version = '1.0.0'; HeaderStr = '{ don''t edit, this file is generated from z80ins.dat; to regenerate, run ''make insdat'' in the compiler directory }'; max_operands = 2; ParamTypes: array [0..40,0..1] of string = ( ('void', 'OT_NONE'), ('r', 'OT_REG8'), ('r''', 'OT_REG8'), ('b', 'OT_IMM3'), ('n', 'OT_IMM8'), ('p', 'OT_IMM_RST'), ('e', 'OT_RELJMP8'), ('nn', 'OT_IMM16'), ('0', 'OT_IMM_VAL0'), ('1', 'OT_IMM_VAL1'), ('2', 'OT_IMM_VAL2'), ('cc', 'OT_COND'), ('C', 'OT_COND_C'), ('NC', 'OT_COND_NC'), ('Z', 'OT_COND_Z'), ('NZ', 'OT_COND_NZ'), ('dd', 'OT_REG16_BC_DE_HL_SP'), ('qq', 'OT_REG16_BC_DE_HL_AF'), ('pp', 'OT_REG16_BC_DE_IX_SP'), ('rr', 'OT_REG16_BC_DE_IY_SP'), ('A', 'OT_REG8_A'), ('I', 'OT_REG8_I'), ('R', 'OT_REG8_R'), ('IX', 'OT_REG16_IX'), ('IY', 'OT_REG16_IY'), ('SP', 'OT_REG16_SP'), ('DE', 'OT_REG16_DE'), ('HL', 'OT_REG16_HL'), ('AF', 'OT_REG16_AF'), ('AF''', 'OT_REG16_AF_'), ('(C)', 'OT_REG8_C_PORT'), ('(n)', 'OT_IMM_PORT'), ('(nn)', 'OT_REF_ADDR16'), ('(BC)', 'OT_REF_BC'), ('(DE)', 'OT_REF_DE'), ('(HL)', 'OT_REF_HL'), ('(SP)', 'OT_REF_SP'), ('(IX)', 'OT_REF_IX'), ('(IY)', 'OT_REF_IY'), ('(IX+d)','OT_REF_IX_d'), ('(IY+d)','OT_REF_IY_d') ); type { TZ80InsDatOutputFiles } TZ80InsDatOutputFiles = class public OpFile: TextFile; NOpFile: TextFile; StdOpNames: TextFile; InsTabFile: TextFile; constructor Create; destructor Destroy;override; end; function PasEncode(const S: string): string; var Ch: Char; InQuotes: Boolean; begin Result:=''; InQuotes:=False; for Ch in S do if (Ch>=#32) and (Ch<=#126) then begin if not InQuotes then begin Result:=Result+''''; InQuotes:=True; end; if Ch='''' then Result:=Result+'''''' else Result:=Result+Ch; end else begin if InQuotes then begin Result:=Result+''''; InQuotes:=False; end; Result:=Result+'#'+IntToStr(Ord(Ch)); end; if InQuotes then Result:=Result+''''; if Result='' then Result:=''''''; end; constructor TZ80InsDatOutputFiles.Create; begin AssignFile(OpFile,'z80op.inc'); Rewrite(OpFile); Writeln(OpFile,HeaderStr); Writeln(OpFile,'('); AssignFile(NOpFile,'z80nop.inc'); Rewrite(NOpFile); Writeln(NOpFile,HeaderStr); AssignFile(StdOpNames,'z80stdopnames.inc'); Rewrite(StdOpNames); Writeln(StdOpNames,HeaderStr); Writeln(StdOpNames,'('); AssignFile(InsTabFile,'z80tab.inc'); Rewrite(InsTabFile); Writeln(InsTabFile,HeaderStr); Writeln(InsTabFile,'('); end; destructor TZ80InsDatOutputFiles.Destroy; begin CloseFile(OpFile); CloseFile(NOpFile); CloseFile(StdOpNames); CloseFile(InsTabFile); inherited Destroy; end; function FindParamType(const ParamTypeStr: string): Integer; var I: Integer; begin for I:=Low(ParamTypes) to High(ParamTypes) do if ParamTypes[I,0]=ParamTypeStr then exit(I); raise Exception.Create('Invalid param type: '''+ParamTypeStr+''''); end; var InsDatFile: TextFile; OutputFiles: TZ80InsDatOutputFiles=nil; S, op, ParamsStr: string; FirstIns: Boolean=true; OpCount: Integer=0; S_Split, S_Params: TStringArray; ParamIdx: Integer; begin writeln('FPC Z80 Instruction Table Converter Version ',Version); AssignFile(InsDatFile,'../z80/z80ins.dat'); Reset(InsDatFile); try OutputFiles:=TZ80InsDatOutputFiles.Create; while not EoF(InsDatFile) do begin Readln(InsDatFile,S); S:=Trim(S); if AnsiStartsStr(';',S) then continue else if AnsiStartsStr('[',S) then begin op:=Copy(S,2,Length(S)-2); if not FirstIns then begin Writeln(OutputFiles.OpFile,','); Writeln(OutputFiles.StdOpNames,','); end; FirstIns:=False; Write(OutputFiles.OpFile,'A_'+op); Write(OutputFiles.StdOpNames,''''+LowerCase(op)+''''); end else if S<>'' then begin Inc(OpCount); if OpCount<>1 then Writeln(OutputFiles.InsTabFile,','); S_Split:=S.Split(' ',TStringSplitOptions.ExcludeEmpty); S_Params:=S_Split[0].Split(',',TStringSplitOptions.ExcludeEmpty); if (Length(S_Params)=1) and (S_Params[0]='void') then SetLength(S_Params,0); Writeln(OutputFiles.InsTabFile,' ('); Writeln(OutputFiles.InsTabFile,' opcode : A_',op,';'); Writeln(OutputFiles.InsTabFile,' ops : ',Length(S_Params),';'); Write(OutputFiles.InsTabFile, ' optypes : ('); if Length(S_Params)>max_operands then raise Exception.Create('Too many operands'); for ParamIdx:=0 to max_operands-1 do begin if ParamIdx<>0 then Write(OutputFiles.InsTabFile,','); if ParamIdx<=High(S_Params) then Write(OutputFiles.InsTabFile,ParamTypes[FindParamType(S_Params[ParamIdx]),1]) else Write(OutputFiles.InsTabFile,'OT_NONE'); end; Writeln(OutputFiles.InsTabFile, ');'); Writeln(OutputFiles.InsTabFile, ' code : ',PasEncode(S_Split[1]),';'); Writeln(OutputFiles.InsTabFile, ' flags : 0'); Write(OutputFiles.InsTabFile, ' )'); end; end; Writeln(OutputFiles.OpFile,');'); Writeln(OutputFiles.StdOpNames,');'); Writeln(OutputFiles.NOpFile,OpCount,';'); Writeln(OutputFiles.InsTabFile); Writeln(OutputFiles.InsTabFile,');'); finally FreeAndNil(OutputFiles); CloseFile(InsDatFile); end; end.