6 ConstantsClass
, FunctionsClass
, PrefixTreeClass
, ResourcesClass
, TypesClass
;
16 pAddress
, pMaxAddress
: Integer;
18 pInstructions
, pOperands
: TPrefixTree
;
19 pOldState
, pState
: THardwareState
;
20 pOnState
: TChangeEvent
;
21 function pErrorSet
: Boolean; virtual;
22 function pInstFromName(Name
: String; var Care
: Boolean): TInstruction
; virtual;
23 function pOperandAt(Input
: String; Position
: Integer): TOperand
; virtual;
24 function pOperandToType(Input
: String): TOperand
; virtual;
25 function pParseInput(var Input
: String; InType
: Integer): TStrings
; virtual;
26 function pTranslateInput(Input
: TStrings
; var Tree
: TPrefixTree
; var Position
: Integer): Boolean; virtual;
27 function pTypeToDesc(Input
: TOperand
): TStrings
; virtual;
28 function pTypeToOperands(Input
: TOperand
): TStrings
; virtual;
29 function pTStringsToInst(Input
: TStrings
; Last
: Integer): String; virtual;
30 procedure pSetError(Input
: String = GLOB_NO_ERROR
; Description
: String = ''); virtual;
31 procedure pSetState(Input
: THardwareState
); virtual;
33 constructor Create
; virtual;
34 function InstructionByName(Name
: String): TInstruction
; virtual;
35 function InstructionValidate(Name
: String): Boolean; virtual;
36 function InstructionsByPrefix(Prefix
: String): TStrings
; virtual;
37 procedure InitializeState
; virtual;
38 destructor Destroy
; override;
39 property LastError
: String read pError
;
40 property Address
: Integer read pAddress write pAddress default
0;
41 property MaxAddress
: Integer read pMaxAddress write pMaxAddress default
0;
42 property OldState
: THardwareState read pOldState write pOldState
;
43 property OnState
: TChangeEvent read pOnState write pOnState
;
44 property State
: THardwareState read pState write pSetState
;
52 pName
, pCode
, pDescription
: String;
55 function pGetCode
: String;
56 procedure pSetCode(Code
: String);
58 constructor Create
; virtual;
59 function Execute
: Boolean; virtual;
60 property HardwareState
: THardware read pHardware write pHardware
;
61 property Name
: String read pName write pName
;
62 property Code
: String read pGetCode write pSetCode
;
63 property Branch
: TBranchType read pBranch write pBranch
;
64 property BranchAddress
: String read pAddr write pAddr
;
65 property Description
: String read pDescription write pDescription
;
70 function CompareStateException(Hardware
: THardware
; Position
: Integer): Boolean;
71 function CompareStateMask(Hardware
: THardware
; Position
: Integer): Boolean;
72 function CompareStateStack(Hardware
: THardware
; Position
: Integer): Boolean;
73 function CompareStateTag(Hardware
: THardware
; Position
: Integer): Boolean;
74 function GetException(State
: THardwareState
; Position
: Integer): Boolean;
75 function GetMask(State
: THardwareState
; Position
: Integer): Boolean;
76 function GetTag(State
: THardwareState
; Position
: Integer): Integer;
78 procedure SetException(var State
: THardwareState
; Position
: Integer; Exception
: Boolean);
79 procedure SetMask(var State
: THardwareState
; Position
: Integer; Mask
: Boolean);
80 procedure SetTag(var State
: THardwareState
; Position
, Tag
: Integer);
84 // ************************************************************************** //
85 // * THardwareState implementation * //
86 // ************************************************************************** //
88 function THardware
.pErrorSet
: Boolean;
90 Result
:= not(pError
= GLOB_NO_ERROR
);
93 function THardware
.pInstFromName(Name
: String; var Care
: Boolean
100 linst
: PInstructionRecord
;
101 loper
: POperandRecord
;
108 lstrings
:= pParseInput(Name
, INTYPE_INSTRUCTION
);
109 if pErrorSet
then Exit
;
111 while pTranslateInput(lstrings
, ltree
, i
) do;
112 if pErrorSet
then Exit
;
115 linst
:= PInstructionrecord(ltree
.Data
);
116 Result
:= TInstruction
.Create
;
118 Result
.Code
:= linst
^.Code
;
119 Result
.Description
:= linst
^.Description
;
120 Result
.Branch
:= linst
^.Branch
;
121 Result
.HardwareState
:= Self
;
122 for i
:= 1 to (Length(lstrings
) - 1) do
124 if IsAddress(lstrings
[i
]) then
126 if (Result
.Branch
= BRANCH_BRANCH
) then
127 Result
.BranchAddress
:= lstrings
[i
];
130 ltree
:= pOperands
.GetDescendant(lstrings
[i
]);
131 loper
:= POperandRecord(ltree
.Data
);
132 lcode
:= loper
^.Code
;
133 llength
:= Length(Result
.Code
);
134 if (llength
> 0) and (Length(lcode
) > 0) then
136 lcode
[1] := Chr(Ord(lcode
[1]) xor Ord(Result
.Code
[llength
]));
137 Result
.Code
:= RemoveCharacter(Result
.Code
);
139 Result
.Code
:= Result
.Code
+ lcode
;
146 function THardware
.pOperandAt(Input
: String; Position
: Integer): TOperand
;
151 if not(Position
> 0) then Exit
;
152 for i
:= 1 to Length(Input
) do
154 if (Position
= 0) then
159 if (Input
[i
] = FPU_SPACE
) then Position
:= Position
- 1;
163 function THardware
.pOperandToType(Input
: String): TOperand
;
167 if IsAddress(Input
) then
169 Result
:= FPU_OPERAND_ADDR
;
172 ltree
:= pOperands
.GetDescendant(Input
);
173 if ValidPrefixTree(ltree
) then
174 Result
:= POperandRecord(ltree
.Data
)^.OperandType
177 pSetError(INST_OPER_UNKNOWN
, Input
);
178 Result
:= FPU_OPERAND_ERROR
;
182 function THardware
.pParseInput(var Input
: String; InType
: Integer): TStrings
;
188 SetLength(Result
, 1);
192 pSetError(INST_NONE
);
195 lspace
:= (Input
[Length(Input
)] = ' ');
196 for i
:= 1 to Length(Input
) do
197 if (Input
[i
] in CHARS_CONTROL
) then
199 pSetError(INST_CHAR_INVALID
, Input
[i
]);
202 Input
:= TrimCharacter(Input
, ' ');
203 Input
:= OmmitEverywhere(Input
, '(', ' ');
204 Input
:= OmmitEverywhere(Input
, ')', ' ');
205 Input
:= OmmitEverywhere(Input
, ',', ' ');
206 Input
:= NeutralizeDoubles(Input
, ' ');
207 Input
:= UpperCase(Input
);
210 pSetError(INST_NONE
);
214 Result
:= MergeStringTStrings(
215 lname
, ParseToStrings(PChar(ParseFirst(lname
, ' ')), ','));
216 if (InType
= INTYPE_PREFIX
) and (Length(Result
) = 1) and lspace
then
217 Result
:= MergeTStringsString(Result
, '');
220 function THardware
.pTranslateInput(Input
: TStrings
; var Tree
: TPrefixTree
;
221 var Position
: Integer): Boolean;
227 if not(Length(Input
) > 0) then Exit
;
228 if (Position
< 0) then Exit
;
229 if (Position
= 0) then
231 ltree
:= pInstructions
;
235 if (Position
= Length(Input
)) then
237 if not ValidPrefixTree(ltree
) then
239 pSetError(INST_OPER_NOT_ENOUGH
);
242 Position
:= Position
+ 1;
244 if not(Position
< Length(Input
)) then Exit
;
245 if (ltree
= nil) then Exit
;
246 if ValidPrefixTree(ltree
) and (Length(ltree
.GetAllDescendants
) = 1) then
248 pSetError(INST_OPER_TOO_MANY
);
251 if not(Position
= 0) then
253 ltype
:= pOperandToType(Input
[Position
]);
254 if (ltype
= FPU_OPERAND_ERROR
) then
256 pSetError(INST_OPER_UNKNOWN
, Input
[Position
]);
259 if (Position
= 1) then ltree
:= ltree
.GetDescendant(ltype
)
260 else ltree
:= ltree
.GetDescendant(FPU_SPACE
+ ltype
);
261 if (ltree
= nil) then
263 pSetError(INST_OPER_INVALID
);
269 ltree
:= ltree
.GetDescendant(Input
[0] + FPU_SPACE
);
270 if (ltree
= nil) then
272 pSetError(INST_INST_UNKNOWN
, Input
[0]);
275 if (Length(Input
) = 1) then
277 ltree
:= ltree
.GetDescendant(FPU_OPERAND_NONE
);
278 if not ValidPrefixTree(ltree
) then
280 pSetError(INST_OPER_NOT_ENOUGH
);
285 Position
:= Position
+ 1;
290 function THardware
.pTypeToDesc(Input
: TOperand
): TStrings
;
294 SetLength(Result
, 1);
295 Result
[0] := sOperandTypes
[0].Description
;
296 for i
:= 1 to (Length(sOperandTypes
) - 1) do
297 if (sOperandTypes
[i
].OperandType
= Input
) then
299 Result
[0] := sOperandTypes
[i
].Description
;
304 function THardware
.pTypeToOperands(Input
: TOperand
): TStrings
;
307 ltrees
: TPrefixTrees
;
308 loperand
: POperandRecord
;
310 SetLength(Result
, 0);
311 ltrees
:= pOperands
.GetAllDescendants
;
312 for i
:= 0 to (Length(ltrees
) - 1) do
314 loperand
:= POperandRecord(ltrees
[i
].Data
);
315 if (loperand
^.OperandType
= Input
) then
316 Result
:= MergeTStringsString(Result
, loperand
^.Name
);
318 if (Input
= FPU_OPERAND_ADDR
) then Result
:= MergeTStringsString(Result
,
319 '<0 - ' + ZeroPaddedInteger(MaxAddress
) + '>');
320 if (Length(Result
) = 0) then pSetError(INST_OPER_UNKNOWN
);
323 function THardware
.pTStringsToInst(Input
: TStrings
; Last
: Integer): String;
328 if not(Length(Input
) > 0) then Exit
;
329 if not(Last
< Length(Input
)) then Exit
;
331 if (Last
< 0) then Exit
;
332 Result
:= Result
+ ' ';
333 for i
:= 1 to Last
do
334 if not(Input
[i
] = '') then
335 Result
:= Result
+ Input
[i
] + ',';
338 procedure THardware
.pSetError(Input
, Description
: String);
341 if not(Description
= '') then pError
:= pError
+ ': "' + Description
+ '"';
344 procedure THardware
.pSetState(Input
: THardwareState
);
347 if not(@OnState
= nil) then OnState(Self
);
350 constructor THardware
.Create
;
356 pInstructions
:= TPrefixTree
.Create
;
357 pOperands
:= TPrefixTree
.Create
;
358 for i
:= 0 to (Length(sInstructions
) - 1) do
359 pInstructions
.Add(sInstructions
[i
].Name
, @sInstructions
[i
]);
360 for i
:= 0 to (Length(sOperands
) - 1) do
362 if not(sOperands
[i
].Default
= '') then
365 Data
:= GetMemory(Length(Default
));
366 Move(PChar(Default
)[0], Data
^, Length(Default
));
367 Code
:= Code
+ AddressToString(Data
);
369 pOperands
.Add(sOperands
[i
].Name
, @sOperands
[i
])
373 function THardware
.InstructionValidate(Name
: String): Boolean;
378 pInstFromName(Name
, lcare
);
382 function THardware
.InstructionByName(Name
: String): TInstruction
;
387 Result
:= pInstFromName(Name
, lcare
);
390 function THardware
.InstructionsByPrefix(Prefix
: String): TStrings
;
393 lstrings
, loperands
: TStrings
;
394 lprefix
, lopers
: String;
396 ltrees
: TPrefixTrees
;
397 linst
: PInstructionRecord
;
400 SetLength(Result
, 0);
401 SetLength(loperands
, 0);
402 SetLength(ltrees
, 0);
403 lstrings
:= pParseInput(Prefix
, INTYPE_PREFIX
);
404 if not(lstrings
[Length(lstrings
)] = '') then
405 lstrings
[Length(lstrings
) - 1] := '';
407 while pTranslateInput(lstrings
, ltree
, lpos
) do;
408 if (lpos
> Length(lstrings
)) and (Length(ltree
.GetAllDescendants
) = 1) then
410 Result
:= MergeTStringsString(Result
, Prefix
);
414 if (lpos
= 0) and (Length(lstrings
) > 1) then Exit
;
415 ltrees
:= ltree
.GetAllDescendants
;
416 lprefix
:= pTStringsToInst(lstrings
, lpos
- 1);
417 for i
:= 0 to (Length(ltrees
) - 1) do
419 linst
:= PInstructionRecord(ltrees
[i
].Data
);
422 if IsPrefixOf(Prefix
, linst
^.Name
) then
424 lopers
:= ParseBeforeFirst(linst
^.Name
, FPU_SPACE
) + ' ';
425 Result
:= RemoveExactString(Result
, lopers
);
426 Result
:= MergeTStringsString(Result
, lopers
);
431 loperands
:= pTypeToOperands(pOperandAt(linst
^.Name
, lpos
));
432 if (Length(loperands
) = 0) then
433 loperands
:= pTypeToDesc(pOperandAt(linst
^.Name
, lpos
));
434 loperands
:= CartesianOfStrings(lprefix
, loperands
);
435 for j
:= 0 to (Length(loperands
) - 1) do
436 if IsPrefixOf(Prefix
, loperands
[j
]) then
438 if not(pOperandAt(linst
^.Name
, lpos
+ 1) = #0) then
439 loperands
[j
] := loperands
[j
] + ',';
440 Result
:= RemoveExactString(Result
, loperands
[j
]);
441 Result
:= MergeTStringsString(Result
, loperands
[j
]);
450 procedure THardware
.InitializeState
;
453 lstate
: THardwareState
;
458 fnsave [lstate.FPUState
]
461 pop dword ptr [lstate.EFlags
]
465 lstate
.FPUState
.ST
[i
] := 0;
470 destructor THardware
.Destroy
;
476 // ************************************************************************** //
477 // * TInstruction implementation * //
478 // ************************************************************************** //
480 function TInstruction
.pGetCode
: String;
482 Result
:= RemoveCharacter(pCode
);
485 procedure TInstruction
.pSetCode(Code
: String);
487 pCode
:= Code
+ INST_OPCODE_RET
;
490 constructor TInstruction
.Create
;
495 Branch
:= BRANCH_NORMAL
;
498 function TInstruction
.Execute
: Boolean;
500 lstate
: THardwareState
;
502 if (Branch
= BRANCH_UNSUPPORTED
) then
507 lstate
:= pHardware
.State
;
512 push [TInstruction
(eax).pCode
]
513 frstor [lstate.FPUState
]
514 push dword ptr [lstate.EFlags
]
515 push dword ptr [lstate.Reg_EAX
]
522 pop dword ptr [lstate.Reg_EAX
]
523 pop dword ptr [lstate.EFlags
]
524 fnsave [lstate.FPUState
]
528 pHardware
.OldState
:= pHardware
.State
;
529 pHardware
.State
:= lstate
;
532 // ************************************************************************** //
533 // * Static Functions implementation * //
534 // ************************************************************************** //
536 function CompareStateException(Hardware
: THardware
; Position
: Integer
541 lexception
:= GetException(Hardware
.State
, Position
);
542 Result
:= (lexception
= GetException(Hardware
.OldState
, Position
));
545 function CompareStateMask(Hardware
: THardware
; Position
: Integer): Boolean;
549 lexception
:= GetMask(Hardware
.State
, Position
);
550 Result
:= (lexception
= GetMask(Hardware
.OldState
, Position
));
553 function CompareStateStack(Hardware
: THardware
; Position
: Integer): Boolean;
558 if (Position
< 0) or (Position
> 7) then Exit
;
559 lsecond
:= @Hardware
.OldState
.FPUState
.ST
[Position
];
560 with Hardware
.State
.FPUState
do
561 Result
:= StringCompare(@ST
[Position
], lsecond
, SizeOf(ST
[Position
]));
564 function CompareStateTag(Hardware
: THardware
; Position
: Integer): Boolean;
568 ltag
:= GetTag(Hardware
.State
, Position
);
569 Result
:= (ltag
= GetTag(Hardware
.OldState
, Position
));
572 function GetException(State
: THardwareState
; Position
: Integer): Boolean;
575 if (Position
< 0) or (Position
> 7) then Exit
;
576 Result
:= not((State
.FPUState
.StatusWord
and (1 shl Position
)) = 0);
579 function GetMask(State
: THardwareState
; Position
: Integer): Boolean;
582 if (Position
< 0) or (Position
> 5) then Exit
;
583 Result
:= not((State
.FPUState
.ControlWord
and (1 shl Position
)) = 0);
586 function GetTag(State
: THardwareState
; Position
: Integer): Integer;
591 if (Position
< 0) or (Position
> 7) then Exit
;
592 with State
.FPUState
do
594 ltop
:= (Position
+ ((StatusWord
shr 11) and 7)) mod 8;
595 Result
:= (TagWord
shr (2 * ltop
)) and 3;
599 procedure SetException(var State
: THardwareState
; Position
: Integer;
602 if (Position
< 0) or (Position
> 7) then Exit
;
603 with State
.FPUState
do
604 if Exception
then StatusWord
:= StatusWord
or (1 shl Position
)
605 else StatusWord
:= StatusWord
and not(1 shl Position
);
608 procedure SetMask(var State
: THardwareState
; Position
: Integer; Mask
: Boolean
611 if (Position
< 0) or (Position
> 5) then Exit
;
612 with State
.FPUState
do
613 if Mask
then ControlWord
:= ControlWord
or (1 shl Position
)
614 else ControlWord
:= ControlWord
and not(1 shl Position
);
617 procedure SetTag(var State
: THardwareState
; Position
, Tag
: Integer);
621 if (Position
< 0) or (Position
> 7) or (Tag
< 0) or (Tag
> 3) then Exit
;
622 with State
.FPUState
do
624 ltop
:= (Position
+ ((StatusWord
shr 11) and 7)) mod 8;
625 ltag
:= TagWord
and not(3 shl (2 * ltop
));
626 TagWord
:= ltag
or (Tag
shl (2 * ltop
));