1 | unit UCompiler;
|
---|
2 |
|
---|
3 | {$mode delphi}
|
---|
4 |
|
---|
5 | interface
|
---|
6 |
|
---|
7 | uses
|
---|
8 | Classes, SysUtils, UMachine;
|
---|
9 |
|
---|
10 | type
|
---|
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 |
|
---|
27 | implementation
|
---|
28 |
|
---|
29 | { TCompiler }
|
---|
30 |
|
---|
31 | function TCompiler.GetPart(var Text: string; Separator: string): string;
|
---|
32 | begin
|
---|
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;
|
---|
40 | end;
|
---|
41 |
|
---|
42 | procedure TCompiler.ParseLine(Line: string; Instructions: TInstructions);
|
---|
43 | var
|
---|
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;
|
---|
57 | begin
|
---|
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;
|
---|
134 | end;
|
---|
135 |
|
---|
136 | function TCompiler.GetOpcodeFromName(Name: string): Integer;
|
---|
137 | var
|
---|
138 | I: Integer;
|
---|
139 | begin
|
---|
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;
|
---|
144 | end;
|
---|
145 |
|
---|
146 | procedure TCompiler.Compile(Instructions: TInstructions);
|
---|
147 | var
|
---|
148 | I: Integer;
|
---|
149 | begin
|
---|
150 | Labels.Clear;
|
---|
151 | Instructions.Clear;
|
---|
152 | for I := 0 to Lines.Count - 1 do begin
|
---|
153 | ParseLine(Lines[I], Instructions);
|
---|
154 | end;
|
---|
155 | end;
|
---|
156 |
|
---|
157 | constructor TCompiler.Create;
|
---|
158 | begin
|
---|
159 | Lines := TStringList.Create;
|
---|
160 | Labels := TStringList.Create;
|
---|
161 | end;
|
---|
162 |
|
---|
163 | destructor TCompiler.Destroy;
|
---|
164 | begin
|
---|
165 | FreeAndNil(Labels);
|
---|
166 | FreeAndNil(Lines);
|
---|
167 | inherited Destroy;
|
---|
168 | end;
|
---|
169 |
|
---|
170 | end.
|
---|
171 |
|
---|