blob: 7f2bbb026b3b3f1171952d0dd51108775b5e32d6 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
{ %opt=-O2 -Sew -vw }
{$inline on}
type
Int96 = packed record
case Integer of
0:
(
{$IFDEF ENDIAN_LITTLE}
Lo32 : DWord;
case Integer of
0:
(
Mid32 : DWord;
Hi32 : LongInt;
);
1:
( Hi64: Int64; );
{$ELSE ENDIAN_LITTLE}
Hi32 : LongInt;
case Integer of
0:
(
Mid32 : DWord;
Lo32 : DWord;
);
1:
( Lo64: QWord; );
{$ENDIF ENDIAN_LITTLE}
);
1:
(
{$IFDEF ENDIAN_LITTLE}
Lo64 : QWord;
{$ELSE ENDIAN_LITTLE}
Hi64 : Int64;
{$ENDIF ENDIAN_LITTLE}
);
end;
operator shl (const Left: Int96; const Right: LongInt) Result : Int96; forward;
operator shr (const Left: Int96; const Right: LongInt) Result : Int96; inline;
begin
if Right >= 0 then
if Right = 32 then begin
Result.Lo32 := Left.Mid32;
Result.Mid32 := Left.Hi32;
Result.Hi32 := 0;
end else if Right = 0 then begin
Result.Lo32 := Left.Lo32;
Result.Mid32 := Left.Mid32;
Result.Hi32 := Left.Hi32;
end else if Right = 64 then begin
Result.Lo32 := Left.Hi32;
Result.Mid32 := 0;
Result.Hi32 := 0;
end else if Right < 32 then begin
Result.Hi32 := Left.Hi32 shr Right;
Result.Mid32 := (Left.Mid32 shr Right) or dword(Left.Hi32 shl (32 - Right));
Result.Lo32 := (Left.Lo32 shr Right) or (Left.Mid32 shl (32 - Right));
end else if Right < 64 then begin
Result.Hi32 := 0;
Result.Mid32 := Left.Hi32 shr (Right-32);
Result.Lo32 := longint(Left.Mid32 shr (Right-32)) or (Left.Hi32 shl (64 - Right));
end else if Right < 96 then begin
Result.Hi32 := 0;
Result.Mid32 := 0;
Result.Lo32 := Left.Hi32 shr (Right-64);
end else begin
Result.Lo32 := 0;
Result.Mid32 := 0;
Result.Hi32 := 0;
end
else
Result := Left shl (-Right);
end;
operator shl (const Left: Int96; const Right: LongInt) Result : Int96; inline;
begin
{ ToDo: optimized code for 64bit cpu's }
if Right >= 0 then
if Right = 32 then begin
Result.Lo32 := 0;
Result.Mid32 := Left.Lo32;
Result.Hi32 := Left.Mid32;
end else if Right = 0 then begin
Result.Lo32 := Left.Lo32;
Result.Mid32 := Left.Mid32;
Result.Hi32 := Left.Hi32;
end else if Right = 64 then begin
Result.Lo32 := 0;
Result.Mid32 := 0;
Result.Hi32 := Left.Lo32;
end else if Right < 32 then begin
Result.Lo32 := Left.Lo32 shl Right;
Result.Mid32 := (Left.Mid32 shl Right) or (Left.Lo32 shr (32 - Right));
Result.Hi32 := (Left.Hi32 shl Right) or longint(Left.Mid32 shr (32 - Right));
end else if Right < 64 then begin
Result.Lo32 := 0;
Result.Mid32 := Left.Lo32 shl (Right-32);
Result.Hi32 := (Left.Mid32 shl (Right-32)) or (Left.Lo32 shr (64 - Right));
end else if Right < 96 then begin
Result.Lo32 := 0;
Result.Mid32 := 0;
Result.Hi32 := Left.Lo32 shl (Right-64);
end else begin
Result.Lo32 := 0;
Result.Mid32 := 0;
Result.Hi32 := 0;
end
else
Result := Left shr (-Right);
end;
operator := (const Right: QWord) Result : Int96; inline;
begin
Result.Lo64 := Right;
Result.Hi32 := 0;
end;
procedure t;
var
a: int96;
begin
a := 500000000000000;
a := a shr 1;
if (a.lo64 <> (500000000000000 shr 1)) or
(a.hi32 <> 0) then
halt(1);
end;
begin
t;
end.
|