1 (*******************************************************************
5 * This unit is only used by the debugger.
7 * Copyright 1996 David Turner, Robert Wilhelm and Werner Lemberg
9 * This file is part of the FreeType project, and may only be used
10 * modified and distributed under the terms of the FreeType project
11 * license, LICENSE.TXT. By continuing to use, modify or distribute
12 * this file you indicate that you have read the license and
13 * understand and accept it fully.
15 ******************************************************************)
21 uses TTTypes
, TTTables
, TTObjs
, TTInterp
;
25 ByteHexStr
= string[2]; (* hex representation of a byte *)
26 ShortHexStr
= string[4]; (* " " " short *)
27 LongHexStr
= string[8]; (* " " " long *)
28 DebugStr
= string[128]; (* disassembled line output *)
32 { A simple record to hold breakpoint information }
33 { it may be completed later with pass count, etc.. }
34 { They must be in a sorted linked list }
36 PBreakPoint
= ^TBreakPoint
;
45 { a record to store line number information and breakpoints list }
47 PRangeRec
= ^TRangeRec
;
53 Disassembled
: PUShort
;
58 { Generate_Range : Generate Line Number information specific to }
61 procedure Generate_Range( CR
: PCodeRange
;
65 { Throw_Range : Discard Line Number Information }
67 procedure Throw_Range( var RR
: TRangeRec
);
69 { Toggle_Break : Toggle a breakpoint }
71 procedure Toggle_Break( var Head
: PBreakPoint
; Range
, Adr
: Int
);
73 { Set_Break : Set a breakpoint on a given address }
75 procedure Set_Break ( var Head
: PBreakPoint
; Range
, Adr
: Int
);
77 { Clear_Break : Clear one specific breakpoint }
79 procedure Clear_Break( var Head
: PBreakPoint
; Bp
: PBreakPoint
);
81 { Clear_All_Breaks : Clear breakpoint list }
83 procedure Clear_All_Breaks( var Head
: PBreakPoint
);
85 { Find_Breakpoint : find one breakpoint at a given address }
87 function Find_BreakPoint( Head
: PBreakPoint
; Range
, IP
: Int
) : PBreakPoint
;
89 { Cur_U_Line : returns the current disassembled line at Code(IP) }
91 function Cur_U_Line( Code
: PByte
; IP
: Int
) : DebugStr
;
93 { Get_Length : returns the length of the current opcode at Code(IP) }
95 function Get_Length( Code
: PByte
; IP
: Int
) : Int
;
97 function Get_Dis_Line( var cr
: TRangeRec
; addr
: Int
) : Int
;
100 { Hex_N : returns an hexadecimal string }
102 function Hex8 ( B
: Byte ) : ByteHexStr
;
103 function Hex16( W
: word ) : ShortHexStr
;
104 function Hex32( L
: Long
) : LongHexStr
;
110 PStorageLong
= ^TStorageLong
;
111 TStorageLong
= record (* do-it-all union record type *)
114 1 : ( S1
, S2
: Integer );
115 2 : ( W1
, W2
: Word );
125 OpStr
: array[ 0..255 ] of String[10]
127 'SVTCA y', (* Set vectors to coordinate axis y *)
128 'SVTCA x', (* Set vectors to coordinate axis x *)
129 'SPvTCA y', (* Set Proj. vec. to coord. axis y *)
130 'SPvTCA x', (* Set Proj. vec. to coord. axis x *)
131 'SFvTCA y', (* Set Free. vec. to coord. axis y *)
132 'SFvTCA x', (* Set Free. vec. to coord. axis x *)
133 'SPvTL //', (* Set Proj. vec. parallel to segment *)
134 'SPvTL +', (* Set Proj. vec. normal to segment *)
135 'SFvTL //', (* Set Free. vec. parallel to segment *)
136 'SFvTL +', (* Set Free. vec. normal to segment *)
137 'SPvFS', (* Set Proj. vec. from stack *)
138 'SFvFS', (* Set Free. vec. from stack *)
139 'GPV', (* Get projection vector *)
140 'GFV', (* Get freedom vector *)
141 'SFvTPv', (* Set free. vec. to proj. vec. *)
142 'ISECT', (* compute intersection *)
144 'SRP0', (* Set reference point 0 *)
145 'SRP1', (* Set reference point 1 *)
146 'SRP2', (* Set reference point 2 *)
147 'SZP0', (* Set Zone Pointer 0 *)
148 'SZP1', (* Set Zone Pointer 1 *)
149 'SZP2', (* Set Zone Pointer 2 *)
150 'SZPS', (* Set all zone pointers *)
151 'SLOOP', (* Set loop counter *)
152 'RTG', (* Round to Grid *)
153 'RTHG', (* Round to Half-Grid *)
154 'SMD', (* Set Minimum Distance *)
156 'JMPR', (* Jump Relative *)
157 'SCvTCi', (* Set CVT *)
401 HexStr
: string[16] = '0123456789abcdef';
403 (*******************************************************************
407 * Description : Returns the string hexadecimal representation
412 * Output : two-chars string
414 *****************************************************************)
416 function Hex8( B
: Byte ) : ByteHexStr
;
421 S
[1] := HexStr
[ 1+( B
shr 4 ) ];
422 S
[2] := HexStr
[ 1+( B
and 15 )];
426 (*******************************************************************
430 * Description : Returns the string hexadecimal representation
435 * Output : four-chars string
437 *****************************************************************)
439 function Hex16( W
: word ) : ShortHexStr
;
441 Hex16
:= Hex8( Hi(w
) )+Hex8( Lo(w
) );
444 (*******************************************************************
448 * Description : Returns the string hexadecimal representation
453 * Output : eight-chars string
455 *****************************************************************)
457 function Hex32( L
: Long
) : LongHexStr
;
459 Hex32
:= Hex16( TStorageLong(L
).W2
)+Hex16( TStorageLong(L
).W1
);
462 (*******************************************************************
464 * Function : Cur_U_Line
466 * Description : Returns a string of the current unassembled
469 * Input : Code base code range
470 * IP current instruction pointer
472 * Output : line string
474 *****************************************************************)
476 function Cur_U_Line( Code
: PByte
; IP
: Int
) : DebugStr
;
484 S
:= Hex16(IP
)+': '+Hex8(Op
)+' '+OpStr
[Op
];
490 S
:= S
+'('+Hex8(n
)+')';
492 S
:= S
+' $'+Hex8( Code
^[Ip
+i
+1] );
497 S
:= S
+'('+Hex8(n
)+')';
499 S
:= S
+' $'+Hex8( Code
^[Ip
+i
*2+1] )+Hex8( Code
^[Ip
+i
*2+2] );
505 S
:= S
+' $'+Hex8( Code
^[Ip
+i
+1] );
511 S
:= S
+' $'+Hex8( Code
^[IP
+i
*2+1] )+Hex8( Code
^[Ip
+i
*2+2] );
519 (*******************************************************************
521 * Function : Get_Length
523 * Description : Returns the length in bytes of the instruction at
524 * current instruction pointer.
526 * Input : Code base code range
527 * IP current instruction pointer
529 * Output : Length in bytes
531 *****************************************************************)
533 function Get_Length( Code
: PByte
; IP
: Int
) : Int
;
543 $40 : N
:= 2 + Code
^[IP
+1];
544 $41 : N
:= 2 + Code
^[IP
+1]*2;
546 $B0..$B7 : N
:= 2 + ( Op
-$B0 );
547 $B8..$BF : N
:= 3 + ( Op
-$B8 )*2
557 (*******************************************************************
559 * Function : Generate_Range
561 * Description : Create a list of unassembled lines for a
568 *****************************************************************)
570 procedure Generate_Range( CR
: PCodeRange
;
572 var RR
: TRangeRec
);
580 RR
.Code
:= PByte( CR
^.Base
);
588 GetMem( RR
.Disassembled
, sizeof(Short
) * N
);
592 RR
.Disassembled
^[Line
] := Adr
;
594 inc( Adr
, Get_Length( RR
.Code
, Adr
));
603 (*******************************************************************
605 * Function : Get_Dis_Line
607 * Description : Returns the line index of address 'addr'
608 * in the coderange 'cr'
610 *****************************************************************)
612 function Get_Dis_Line( var cr
: TRangeRec
; addr
: Int
) : Int
;
616 if (cr
.NLines
= 0) or
617 (addr
> cr
.Disassembled
^[cr
.Nlines
-1] ) then
628 if cr
.Disassembled
^[l
] = addr
then
634 if cr
.Disassembled
^[r
] = addr
then
641 if cr
.Disassembled
^[m
] = addr
then
647 if cr
.Disassembled
^[m
] < addr
then
653 if cr
.Disassembled
^[r
] = addr
then
663 (*******************************************************************
665 * Function : Throw_Range
667 * Description : Destroys a list of unassembled lines for a
674 *****************************************************************)
676 procedure Throw_Range( var RR
: TRangeRec
);
678 B
, Bnext
: PBreakPoint
;
682 FreeMem( RR
.Disassembled
, RR
.Size
* sizeof(Short
) );
684 RR
.Disassembled
:= nil;
700 (*******************************************************************
702 * Function : Set_Break
704 * Description : Sets a Breakpoint ON
710 *****************************************************************)
712 procedure Set_Break( var Head
: PBreakPoint
;
723 while (Cur
<> nil) and (Cur
^.Address
< Adr
) do
731 if (Cur
^.Address
= Adr
) and (Cur
^.Range
= Range
) then exit
;
744 (*******************************************************************
746 * Function : Clear_Break
748 * Description : Clears a breakpoint OFF
754 *****************************************************************)
756 procedure Clear_Break( var Head
: PBreakPoint
; Bp
: PBreakPoint
);
764 while (Cur
<> nil) and (Cur
<> Bp
) do
770 if Cur
= nil then exit
;
775 Old
^.Next
:= Cur
^.Next
;
780 procedure Toggle_Break( var Head
: PBreakPoint
; Range
, Adr
: Int
);
784 Bp
:= Find_BreakPoint( Head
, Range
, Adr
);
785 if Bp
<> nil then Clear_Break( Head
, Bp
)
786 else Set_Break( Head
, Range
, Adr
);
789 (*******************************************************************
791 * Function : Clear_All_Breaks
793 * Description : Clears all breakpoints
799 *****************************************************************)
801 procedure Clear_All_Breaks( var Head
: PBreakPoint
);
817 (*******************************************************************
819 * Function : Find_BreakPoint
821 * Description : Find a breakpoint at address IP
823 * Input : Head break points sorted linked list
824 * IP address of expected breakpoint
826 * Output : pointer to breakpoint if found
829 *****************************************************************)
831 function Find_BreakPoint( Head
: PBreakPoint
; Range
, IP
: Int
) : PBreakPoint
;
841 if (Cur
^.Address
= IP
) and
842 (Cur
^.Range
= Range
) then Res
:= Cur
;
844 if (Cur
^.Address
>= IP
) then Cur
:= nil
845 else Cur
:= Cur
^.Next
;
848 Find_BreakPoint
:= Res
;