source: branches/Z80/UZ80Compiler.pas

Last change on this file was 3, checked in by george, 15 years ago
  • Přidáno: Vývojová větev Void.
File size: 5.4 KB
Line 
1unit UZ80Compiler;
2
3{$mode Delphi}{$H+}
4
5interface
6
7uses
8 Classes, SysUtils, UDynamicNumber;
9
10type
11 TMaskedValue = class
12 private
13 function GetSize: Integer;
14 procedure SetSize(const AValue: Integer);
15 public
16 Value: TDynamicNumber;
17 Mask: TDynamicNumber;
18 property Size: Integer read GetSize write SetSize;
19 constructor Create;
20 destructor Destroy; override;
21 end;
22
23 TStringEnumeration = class
24 Values: TStringList;
25 constructor Create;
26 destructor Destroy; override;
27 end;
28
29 TOperandType = (otEnumeration, otConstant);
30
31 TOperand = class
32 OperandType: TOperandType;
33 MaskedValue: TMaskedValue;
34 Enumeration: TStringEnumeration;
35 constructor Create;
36 destructor Destroy; override;
37 end;
38
39 TOpcode = class
40 Name: string;
41 Cycles: Integer;
42 Operands: TList;
43 MaskedValue: TMaskedValue;
44 constructor Create;
45 destructor Destroy; override;
46 end;
47
48 { TZ80Compiler }
49
50 TZ80Compiler = class
51 private
52 OperandEnumerations: TList;
53 Opcodes: TList;
54 MachineCode: TMemoryStream;
55 procedure InitOpcodes;
56 function FindOpcodeByName(Name: string): TOpcode;
57 function ParseLine(var Text: string; Separator: string = ' '): string;
58 public
59 procedure Load(StringList: TStringList);
60 constructor Create;
61 destructor Destroy; override;
62 end;
63
64implementation
65
66{ TZ80Compiler }
67
68procedure TZ80Compiler.InitOpcodes;
69var
70 SigleRegistersEnum: TStringEnumeration;
71begin
72 SigleRegistersEnum := TStringEnumeration.Create;
73 with SigleRegistersEnum do begin
74 Values.Add('B');
75 Values.Add('C');
76 Values.Add('D');
77 Values.Add('E');
78 Values.Add('H');
79 Values.Add('L');
80 Values.Add('(HL)');
81 Values.Add('A');
82 end;
83 OperandEnumerations.Add(SigleRegistersEnum);
84
85 with TOpcode(Opcodes[Opcodes.Add(TOpcode.Create)]) do begin
86 Name := 'NOP';
87 with MaskedValue do begin
88 Value.Assign(0);
89 Mask.Assign($ff);
90 end;
91 end;
92 with TOpcode(Opcodes[Opcodes.Add(TOpcode.Create)]) do begin
93 Name := 'INC';
94 with MaskedValue do begin
95 Value.Assign($04);
96 Mask.Assign($c7);
97 end;
98 with TOperand(Operands[Operands.Add(TOperand.Create)]) do begin
99 OperandType := otEnumeration;
100 Enumeration := SigleRegistersEnum;
101 with MaskedValue do begin
102 Value.Assign($00);
103 Mask.Assign($38);
104 end;
105 end;
106 end;
107end;
108
109function TZ80Compiler.FindOpcodeByName(Name: string): TOpcode;
110var
111 I: Integer;
112begin
113 I := 0;
114 while (I < Opcodes.Count) and (TOpcode(Opcodes[I]).Name <> Name) do Inc(I);
115 if I < Opcodes.Count then Result := Opcodes[I]
116 else Result := nil;
117end;
118
119function TZ80Compiler.ParseLine(var Text: string; Separator: string = ' '): string;
120begin
121 Text := Trim(Text);
122 Result := Copy(Text, 1, Pos(Separator, Text) - 1);
123 if Result <> '' then
124 Delete(Text, 1, Length(Result) + Length(Separator));
125end;
126
127procedure TZ80Compiler.Load(StringList: TStringList);
128var
129 I: Integer;
130 Line: string;
131 InstructionName: string;
132 Instruction: TOpcode;
133 Parameter: string;
134 begin
135 for I := 0 to StringList.Count - 1 do begin
136 Line := Trim(StringList[I]);
137 Line := StringReplace(Line, #9, ' ', [rfReplaceAll]);
138 if Length(Line) > 0 then begin
139 if Line[1] = ';' then Continue; // Skip commented lines
140 InstructionName := ParseLine(Line);
141 Instruction := FindOpcodeByName(InstructionName);
142 if Assigned(Instruction) then begin
143 WriteLn(InstructionName);
144 if Pos(',', Line) > 0 then Parameter := ParseLine(Line, ',')
145 else Parameter := Line;
146 WriteLn(Parameter);
147 end else WriteLn('Unknown instruction name "' + InstructionName + '"');
148 end;
149 end;
150end;
151
152constructor TZ80Compiler.Create;
153begin
154 MachineCode := TMemoryStream.Create;
155 Opcodes := TList.Create;
156 OperandEnumerations := TList.Create;
157 InitOpcodes;
158end;
159
160destructor TZ80Compiler.Destroy;
161var
162 I: Integer;
163begin
164 for I := 0 to Opcodes.Count - 1 do
165 TOpcode(Opcodes[I]).Destroy;
166 Opcodes.Destroy;
167 for I := 0 to OperandEnumerations.Count - 1 do
168 TStringEnumeration(OperandEnumerations[I]).Destroy;
169 OperandEnumerations.Destroy;
170 MachineCode.Destroy;
171 inherited Destroy;
172end;
173
174{ TMaskedValue }
175
176function TMaskedValue.GetSize: Integer;
177begin
178 Result := Value.Size;
179end;
180
181procedure TMaskedValue.SetSize(const AValue: Integer);
182begin
183 Value.Size := AValue;
184 Mask.Size := AValue;
185end;
186
187constructor TMaskedValue.Create;
188begin
189 Mask := TDynamicNumber.Create;
190 Value := TDynamicNumber.Create;
191end;
192
193destructor TMaskedValue.Destroy;
194begin
195 Mask.Destroy;
196 Value.Destroy;
197 inherited Destroy;
198end;
199
200{ TOpcode }
201
202constructor TOpcode.Create;
203begin
204 MaskedValue := TMaskedValue.Create;
205 Operands := TList.Create;
206end;
207
208destructor TOpcode.Destroy;
209var
210 I: Integer;
211begin
212 for I := 0 to Operands.Count - 1 do
213 TOperand(Operands[I]).Destroy;
214 Operands.Destroy;
215 MaskedValue.Destroy;
216 inherited Destroy;
217end;
218
219{ TOperand }
220
221constructor TOperand.Create;
222begin
223 MaskedValue := TMaskedValue.Create;
224 Enumeration := nil;
225end;
226
227destructor TOperand.Destroy;
228begin
229 MaskedValue.Destroy;
230 inherited Destroy;
231end;
232
233{ TStringEnumeration }
234
235constructor TStringEnumeration.Create;
236begin
237 Values := TStringList.Create;
238end;
239
240destructor TStringEnumeration.Destroy;
241begin
242 Values.Destroy;
243 inherited Destroy;
244end;
245
246end.
Note: See TracBrowser for help on using the repository browser.