Changeset 185 for branches/virtualcpu4/UAssembler.pas
- Timestamp:
- May 1, 2019, 9:48:46 PM (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/virtualcpu4/UAssembler.pas
r184 r185 20 20 Text: string; 21 21 procedure Expect(Text: string); 22 function IsOperator(C: Char): Boolean; 23 function IsWhiteSpace(C: Char): Boolean; 22 24 function ReadNext: string; 23 25 function EndOfText: Boolean; … … 25 27 end; 26 28 29 TLabelRef = class 30 Address: QWord; 31 BitWidth: TBitWidth; 32 Relative: Boolean; 33 end; 34 35 { TLabel } 36 27 37 TLabel = class 28 38 Name: string; 29 39 Address: QWord; 30 end; 40 Refs: TFPGList<TLabelRef>; 41 constructor Create; 42 destructor Destroy; override; 43 end; 44 45 { TLabels } 31 46 32 47 TLabels = class(TFPGObjecTList<TLabel>) 33 48 function SearchByName(Name: string): TLabel; 34 49 end; 35 50 … … 40 55 FOnError: TErrorEvent; 41 56 OpcodeDefs: TOpcodeDefs; 57 InstructionIP: QWord; 42 58 procedure Error(Text: string); 43 59 procedure ParseParam(Param: TOpcodeParam); 60 procedure WriteRefAddr(Name: string; Relative: Boolean = False); 61 procedure WriteRefData(Name: string); 62 procedure UpdateLabelRef; 63 procedure ParseInstruction; 44 64 public 45 65 Parser: TParser; … … 56 76 implementation 57 77 78 { TLabels } 79 80 function TLabels.SearchByName(Name: string): TLabel; 81 var 82 I: Integer; 83 begin 84 I := 0; 85 while (I < Count) and (Items[I].Name <> Name) do Inc(I); 86 if I < Count then Result := Items[I] 87 else Result := nil; 88 end; 89 90 { TLabel } 91 92 constructor TLabel.Create; 93 begin 94 Refs := TFPGList<TLabelRef>.Create; 95 end; 96 97 destructor TLabel.Destroy; 98 begin 99 Refs.Free; 100 inherited Destroy; 101 end; 102 58 103 { TParser } 59 104 … … 72 117 end; 73 118 119 function TParser.IsOperator(C: Char): Boolean; 120 begin 121 Result := (C = ',') or (C = ';'); 122 end; 123 124 function TParser.IsWhiteSpace(C: Char): Boolean; 125 begin 126 Result := (C = ' ') or (C = #8); 127 end; 128 74 129 function TParser.ReadNext: string; 75 130 var … … 78 133 Text := Trim(Text); 79 134 P := 1; 80 if (Length(Text) > 0) and (Text[P] = ',') then begin135 if (Length(Text) > 0) and IsOperator(Text[P]) then begin 81 136 Result := Text[P]; 82 137 Delete(Text, 1, 1); 83 138 end else begin 84 while (P <= Length(Text)) and (Text[P] <> ' ') and (Text[P] <> ',') do Inc(P);139 while (P <= Length(Text)) and not IsWhiteSpace(Text[P]) and not IsOperator(Text[P]) do Inc(P); 85 140 Result := Copy(Text, 1, P - 1); 86 141 Delete(Text, 1, P - 1); … … 103 158 var 104 159 Reg: TRegIndex; 105 Addr: QWord;160 Addr: Int64; 106 161 Next: string; 107 162 begin … … 115 170 if Param = prData then begin 116 171 Next := Parser.ReadNext; 117 InstructionWriter.WriteData(StrToInt(Next)); 172 if TryStrToInt64(Next, Addr) then 173 InstructionWriter.WriteData(Addr) 174 else WriteRefData(Next); 118 175 end else 119 176 if Param = prAddr then begin 120 177 Next := Parser.ReadNext; 121 InstructionWriter.WriteAddress(StrToInt(Next)); 178 if TryStrToInt64(Next, Addr) then 179 InstructionWriter.WriteAddress(Addr) 180 else WriteRefAddr(Next); 122 181 end else 123 182 if Param = prAddrRel then begin 124 183 Next := Parser.ReadNext; 125 InstructionWriter.WriteAddress(StrToInt(Next)); 126 end; 184 if TryStrToInt64(Next, Addr) then 185 InstructionWriter.WriteAddress(InstructionWriter.IP + Addr) 186 else WriteRefAddr(Next, True); 187 end; 188 end; 189 190 procedure TAssembler.WriteRefAddr(Name: string; Relative: Boolean = False); 191 var 192 L: TLabel; 193 NewRef: TLabelRef; 194 begin 195 L := Labels.SearchByName(Name); 196 if Assigned(L) then begin 197 if Relative then 198 InstructionWriter.WriteAddressSigned(InstructionWriter.GetRelativeAddr( 199 InstructionWriter.AddrSize, InstructionIP, L.Address)) 200 else InstructionWriter.WriteAddress(L.Address); 201 end else begin 202 L := TLabel.Create; 203 L.Name := Name; 204 NewRef := TLabelRef.Create; 205 NewRef.Address := InstructionWriter.IP; 206 NewRef.BitWidth := InstructionWriter.AddrSize; 207 if Relative then NewRef.Relative := True; 208 L.Refs.Add(NewRef); 209 Labels.Add(L); 210 InstructionWriter.WriteAddress(0); 211 end; 212 end; 213 214 procedure TAssembler.WriteRefData(Name: string); 215 var 216 L: TLabel; 217 NewRef: TLabelRef; 218 begin 219 L := Labels.SearchByName(Name); 220 if Assigned(L) then begin 221 InstructionWriter.WriteData(L.Address); 222 end else begin 223 L := TLabel.Create; 224 L.Name := Name; 225 NewRef := TLabelRef.Create; 226 NewRef.Address := InstructionWriter.IP; 227 NewRef.BitWidth := InstructionWriter.DataSize; 228 L.Refs.Add(NewRef); 229 Labels.Add(L); 230 InstructionWriter.WriteData(0); 231 end; 232 end; 233 234 procedure TAssembler.UpdateLabelRef; 235 var 236 I: Integer; 237 R: Integer; 238 begin 239 for I := 0 to Labels.Count - 1 do 240 with TLabel(Labels[I]) do begin 241 for R := 0 to Refs.Count - 1 do 242 begin 243 InstructionWriter.IP := Refs[R].Address; 244 InstructionWriter.AddrSize := Refs[R].BitWidth; 245 if Refs[R].Relative then InstructionWriter.WriteAddressSigned(InstructionWriter.GetRelativeAddr( 246 InstructionWriter.AddrSize, InstructionWriter.IP - 1, Address)) 247 else InstructionWriter.WriteAddress(Address); 248 end; 249 end; 250 end; 251 252 procedure TAssembler.ParseInstruction; 253 var 254 Next: string; 255 LabelName: string; 256 NewLabel: TLabel; 257 OpcodeDef: TOpcodeDef; 258 begin 259 Next := Parser.ReadNext; 260 if Next = '' then Exit; 261 if (Length(Next) > 0) and (Next[Length(Next)] = ':') then begin 262 LabelName := Copy(Next, 1, Length(Next) - 1); 263 NewLabel := Labels.SearchByName(LabelName); 264 if not Assigned(NewLabel) then begin 265 NewLabel := TLabel.Create; 266 NewLabel.Name := LabelName; 267 Labels.Add(NewLabel); 268 end; 269 NewLabel.Address := InstructionWriter.IP; 270 Next := Parser.ReadNext; 271 end; 272 if Next = '' then Exit; 273 OpcodeDef := OpcodeDefs.SearchByName(Next); 274 if Assigned(OpcodeDef) then begin 275 if OpcodeDef.Prefix then InstructionWriter.Prefix := True; 276 if OpcodeDef.Opcode = opDataPrefix16 then InstructionWriter.DataSize := bw8 277 else if OpcodeDef.Opcode = opDataPrefix16 then InstructionWriter.DataSize := bw16 278 else if OpcodeDef.Opcode = opDataPrefix32 then InstructionWriter.DataSize := bw32 279 else if OpcodeDef.Opcode = opDataPrefix64 then InstructionWriter.DataSize := bw64 280 else if OpcodeDef.Opcode = opAddrPrefix8 then InstructionWriter.AddrSize := bw8 281 else if OpcodeDef.Opcode = opAddrPrefix16 then InstructionWriter.AddrSize := bw16 282 else if OpcodeDef.Opcode = opAddrPrefix32 then InstructionWriter.AddrSize := bw32 283 else if OpcodeDef.Opcode = opAddrPrefix64 then InstructionWriter.AddrSize := bw64; 284 InstructionIP := InstructionWriter.IP; 285 InstructionWriter.Write8(Byte(OpcodeDef.Opcode)); 286 ParseParam(OpcodeDef.Param1); 287 if OpcodeDef.Param2 <> prNone then begin 288 Parser.Expect(','); 289 ParseParam(OpcodeDef.Param2); 290 if OpcodeDef.Param3 <> prNone then begin 291 Parser.Expect(','); 292 ParseParam(OpcodeDef.Param3); 293 end; 294 end; 295 if not OpcodeDef.Prefix then begin 296 InstructionWriter.DataSize := InstructionWriter.DataSizeBase; 297 InstructionWriter.AddrSize := InstructionWriter.AddrSizeBase; 298 end; 299 end else 300 if Next = 'STRING' then begin 301 Next := Parser.ReadNext; 302 if (Length(Next) >= 2) and (Next[1] = '''') and (Next[Length(Next)] = '''') then 303 InstructionWriter.WriteString(Copy(Next, 2, Length(Next) - 2)); 304 end else 305 Error('Unknown instruction ' + Next); 127 306 end; 128 307 … … 130 309 var 131 310 I: Integer; 132 NewLabel: TLabel;133 311 Next: string; 134 OpcodeDef: TOpcodeDef;135 312 begin 136 313 InstructionWriter.Init; … … 138 315 for I := 0 to Source.Count - 1 do begin 139 316 Parser.Text := Source[I]; 140 Next := Parser.ReadNext; 141 if (Length(Next) > 0) and (Next[Length(Next)] = ':') then begin 142 NewLabel := TLabel.Create; 143 NewLabel.Name := Copy(Next, 1, Length(Next) - 1); 144 //NewLabel.Address := ; 145 Labels.Add(NewLabel); 317 ParseInstruction; 318 repeat 146 319 Next := Parser.ReadNext; 147 end; 148 OpcodeDef := OpcodeDefs.SearchByName(Next); 149 if Assigned(OpcodeDef) then begin 150 InstructionWriter.Write8(Byte(OpcodeDef.Opcode)); 151 ParseParam(OpcodeDef.Param1); 152 if OpcodeDef.Param2 <> prNone then begin 153 Parser.Expect(','); 154 ParseParam(OpcodeDef.Param2); 155 if OpcodeDef.Param3 <> prNone then begin 156 Parser.Expect(','); 157 ParseParam(OpcodeDef.Param3); 158 end; 159 end; 160 end else Error('Unknown instruction ' + Next); 161 end; 320 if (Next = '') or (Next <> ';') then Break; 321 ParseInstruction; 322 until False; 323 end; 324 UpdateLabelRef; 162 325 end; 163 326
Note:
See TracChangeset
for help on using the changeset viewer.