source: branches/virt simple/UCompiler.pas

Last change on this file was 138, checked in by chronos, 6 years ago
  • Modified: Preparation for support for multiple memory types.
File size: 4.5 KB
Line 
1unit UCompiler;
2
3{$mode delphi}
4
5interface
6
7uses
8 Classes, SysUtils, UMachine;
9
10type
11 { TCompiler }
12
13 TCompiler = class
14 private
15 Labels: TStringList;
16 function GetPart(var Text: string; Separator: string): string;
17 procedure ParseLine(Line: string; Instructions: TInstructions);
18 function GetOpcodeFromName(Name: string): Integer;
19 public
20 Lines: TStringList;
21 procedure Compile(Instructions: TInstructions);
22 constructor Create;
23 destructor Destroy; override;
24 end;
25
26
27implementation
28
29{ TCompiler }
30
31function TCompiler.GetPart(var Text: string; Separator: string): string;
32begin
33 if Pos(Separator, Text) > 0 then begin
34 Result := Copy(Text, 1, Pos(Separator, Text) - 1);
35 Delete(Text, 1, Length(Result) + Length(Separator));
36 end else begin
37 Result := Text;
38 Text := '';
39 end;
40end;
41
42procedure TCompiler.ParseLine(Line: string; Instructions: TInstructions);
43var
44 Name: string;
45 OpcodeIndex: Integer;
46 Param1: string;
47 Param2: string;
48 ParamType1: TParamType;
49 Indirect1: TMemoryType;
50 Value1: Integer;
51 ParamType2: TParamType;
52 Indirect2: TMemoryType;
53 Value2: Integer;
54 OutValue: Integer;
55 LineLabel: string;
56 I: Integer;
57begin
58 Line := Trim(Line);
59 // Strip comments
60 if Pos(';', Line) > 0 then begin
61 Line := Trim(Copy(Line, 1, Pos(';', Line) - 1));
62 end;
63 if Pos(':', Line) > 0 then begin
64 LineLabel := Trim(GetPart(Line, ':'));
65 if Labels.IndexOf(LineLabel) <> -1 then raise Exception.Create('Label ' + LineLabel + ' already defined');
66 Labels.AddObject(LineLabel, TObject(Instructions.Count));
67 end;
68 if Line = '' then Exit;
69 Name := Trim(GetPart(Line, ' '));
70 OpcodeIndex := GetOpcodeFromName(Name);
71 if OpcodeIndex = -1 then raise Exception.Create('Unsupported instruction name: ' + Name)
72 else begin
73 Param1 := Trim(GetPart(Line, ','));
74 if Param1 <> '' then begin
75 if (Copy(Param1, 1, 1) = '[') and (Copy(Param1, Length(Param1), 1) = ']') then begin
76 Indirect1 := mtData;
77 Param1 := Trim(Copy(Param1, 2, Length(Param1) - 2));
78 end else Indirect1 := mtNone;
79 if Copy(Param1, 1, 1) = 'R' then begin
80 ParamType1 := ptRegister;
81 Value1 := StrToInt(Copy(Param1, 2, Length(Param1)));
82 end else
83 if Param1 = 'IP' then begin
84 ParamType1 := ptSpecialRegister;
85 Value1 := 0;
86 end else
87 if Param1 = 'SP' then begin
88 ParamType1 := ptSpecialRegister;
89 Value1 := 1;
90 end else begin
91 ParamType1 := ptConst;
92 if TryStrToInt(Param1, OutValue) then begin
93 Value1 := OutValue;
94 end else begin
95 I := Labels.IndexOf(Param1);
96 if I <> -1 then Value1 := Integer(Labels.Objects[I])
97 else raise Exception.Create('Unsupported parameter value ' + Param1);
98 end;
99 end;
100 end else ParamType1 := ptNone;
101
102 Param2 := Trim(GetPart(Line, ','));
103 if Param2 <> '' then begin
104 if (Copy(Param2, 1, 1) = '[') and (Copy(Param2, Length(Param2), 1) = ']') then begin
105 Indirect2 := mtData;
106 Param2 := Trim(Copy(Param2, 2, Length(Param2) - 2));
107 end else Indirect2 := mtNone;
108 if Copy(Param2, 1, 1) = 'R' then begin
109 ParamType2 := ptRegister;
110 Value2 := StrToInt(Copy(Param2, 2, Length(Param2)));
111 end else
112 if Param2 = 'IP' then begin
113 ParamType2 := ptSpecialRegister;
114 Value2 := 0;
115 end else
116 if Param2 = 'SP' then begin
117 ParamType2 := ptSpecialRegister;
118 Value2 := 1;
119 end else begin
120 ParamType2 := ptConst;
121 if TryStrToInt(Param2, OutValue) then begin
122 Value2 := OutValue;
123 end else begin
124 I := Labels.IndexOf(Param2);
125 if I <> -1 then Value2 := Integer(Labels.Objects[I])
126 else raise Exception.Create('Unsupported parameter value ' + Param2);
127 end;
128 end;
129 end else ParamType2 := ptNone;
130
131 Instructions.AddInst(TOpcode(OpcodeIndex), ParamType1, Indirect1, Value1,
132 ParamType2, Indirect2, Value2);
133 end;
134end;
135
136function TCompiler.GetOpcodeFromName(Name: string): Integer;
137var
138 I: Integer;
139begin
140 I := 0;
141 while (I < Length(OpcodeString)) and (OpcodeString[TOpcode(I)] <> Name) do Inc(I);
142 if I < Length(OpcodeString) then Result := I
143 else Result := -1;
144end;
145
146procedure TCompiler.Compile(Instructions: TInstructions);
147var
148 I: Integer;
149begin
150 Labels.Clear;
151 Instructions.Clear;
152 for I := 0 to Lines.Count - 1 do begin
153 ParseLine(Lines[I], Instructions);
154 end;
155end;
156
157constructor TCompiler.Create;
158begin
159 Lines := TStringList.Create;
160 Labels := TStringList.Create;
161end;
162
163destructor TCompiler.Destroy;
164begin
165 FreeAndNil(Labels);
166 FreeAndNil(Lines);
167 inherited Destroy;
168end;
169
170end.
171
Note: See TracBrowser for help on using the repository browser.