Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1186 | savelij | 1 | /* codechunks.c */ |
2 | /*****************************************************************************/ |
||
3 | /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */ |
||
4 | /* */ |
||
5 | /* AS-Portierung */ |
||
6 | /* */ |
||
7 | /* Maintain address ranges & included code */ |
||
8 | /* */ |
||
9 | /*****************************************************************************/ |
||
10 | |||
11 | #include "stdinc.h" |
||
12 | |||
13 | #include "codechunks.h" |
||
14 | |||
15 | static void SetCodePtr(tCodeChunk *pChunk, void *pCode, unsigned Granularity) |
||
16 | { |
||
17 | switch ((pChunk->Granularity = Granularity)) |
||
18 | { |
||
19 | case 4: |
||
20 | pChunk->pLongCode = (LongWord*)pCode; |
||
21 | pChunk->pWordCode = NULL; |
||
22 | pChunk->pCode = NULL; |
||
23 | break; |
||
24 | case 2: |
||
25 | pChunk->pLongCode = (LongWord*)pCode; |
||
26 | pChunk->pWordCode = (Word*)pCode; |
||
27 | pChunk->pCode = NULL; |
||
28 | break; |
||
29 | case 1: |
||
30 | pChunk->pLongCode = (LongWord*)pCode; |
||
31 | pChunk->pWordCode = (Word*)pCode; |
||
32 | pChunk->pCode = (Byte*)pCode; |
||
33 | break; |
||
34 | } |
||
35 | } |
||
36 | |||
37 | static void CheckOverlap(const tCodeChunk *pChunk1, const tCodeChunk *pChunk2) |
||
38 | { |
||
39 | LargeWord OverlapStart, OverlapEnd; |
||
40 | |||
41 | OverlapStart = max(pChunk1->Start, pChunk2->Start); |
||
42 | OverlapEnd = min(pChunk1->Start + pChunk1->Length - 1, pChunk2->Start + pChunk2->Length - 1); |
||
43 | if (OverlapStart <= OverlapEnd) |
||
44 | fprintf(stderr, "code chunk overlap\n"); |
||
45 | } |
||
46 | |||
47 | static int SetCodeChunkListAllocLen(tCodeChunkList *pCodeChunkList, unsigned NewAllocLen) |
||
48 | { |
||
49 | int Result; |
||
50 | |||
51 | if (NewAllocLen < pCodeChunkList->RealLen) |
||
52 | { |
||
53 | unsigned z; |
||
54 | |||
55 | for (z = NewAllocLen; z < pCodeChunkList->RealLen; z++) |
||
56 | FreeCodeChunk(pCodeChunkList->Chunks + z); |
||
57 | pCodeChunkList->RealLen = NewAllocLen; |
||
58 | } |
||
59 | |||
60 | if (!pCodeChunkList->AllocLen) |
||
61 | { |
||
62 | pCodeChunkList->Chunks = (tCodeChunk*)malloc(NewAllocLen * sizeof(tCodeChunk)); |
||
63 | Result = pCodeChunkList->Chunks ? 0 : ENOMEM; |
||
64 | } |
||
65 | else |
||
66 | { |
||
67 | tCodeChunk *pNewChunks = (tCodeChunk*)realloc(pCodeChunkList->Chunks, NewAllocLen * sizeof(tCodeChunk)); |
||
68 | Result = pNewChunks ? 0 : ENOMEM; |
||
69 | if (!Result) |
||
70 | pCodeChunkList->Chunks = pNewChunks; |
||
71 | } |
||
72 | |||
73 | if (!Result) |
||
74 | { |
||
75 | pCodeChunkList->AllocLen = NewAllocLen; |
||
76 | if (!pCodeChunkList->AllocLen) |
||
77 | pCodeChunkList->Chunks = NULL; |
||
78 | } |
||
79 | return Result; |
||
80 | } |
||
81 | |||
82 | void InitCodeChunk(tCodeChunk *pChunk) |
||
83 | { |
||
84 | pChunk->Start = pChunk->Length = 0; |
||
85 | pChunk->Granularity = 1; |
||
86 | SetCodePtr(pChunk, NULL, 1); |
||
87 | } |
||
88 | |||
89 | int ReadCodeChunk(tCodeChunk *pChunk, const char *pFileName, LargeWord Start, LargeWord Length, unsigned Granularity) |
||
90 | { |
||
91 | FILE *pFile = NULL; |
||
92 | Byte *pCode = NULL; |
||
93 | int Result; |
||
94 | |||
95 | UNUSED(Granularity); |
||
96 | FreeCodeChunk(pChunk); |
||
97 | |||
98 | pFile = fopen(pFileName, OPENRDMODE); |
||
99 | if (!pFile) |
||
100 | { |
||
101 | Result = EIO; |
||
102 | goto func_exit; |
||
103 | } |
||
104 | |||
105 | if (!Length) |
||
106 | { |
||
107 | fseek(pFile, 0, SEEK_END); |
||
108 | Length = ftell(pFile); |
||
109 | fseek(pFile, 0, SEEK_SET); |
||
110 | } |
||
111 | |||
112 | pCode = (Byte*)malloc(Length); |
||
113 | if (!pCode) |
||
114 | { |
||
115 | Result = ENOMEM; |
||
116 | goto func_exit; |
||
117 | } |
||
118 | |||
119 | if (fread(pCode, 1, Length, pFile) != Length) |
||
120 | { |
||
121 | Result = EIO; |
||
122 | goto func_exit; |
||
123 | } |
||
124 | |||
125 | pChunk->Start = Start; |
||
126 | pChunk->Length = Length; |
||
127 | SetCodePtr(pChunk, pCode, 1); |
||
128 | pCode = NULL; |
||
129 | |||
130 | Result = 0; |
||
131 | |||
132 | func_exit: |
||
133 | if (pCode) |
||
134 | free(pCode); |
||
135 | if (pFile) |
||
136 | fclose(pFile); |
||
137 | return Result; |
||
138 | } |
||
139 | |||
140 | void FreeCodeChunk(tCodeChunk *pChunk) |
||
141 | { |
||
142 | if (pChunk->pCode) |
||
143 | free(pChunk->pCode); |
||
144 | InitCodeChunk(pChunk); |
||
145 | } |
||
146 | |||
147 | void InitCodeChunkList(tCodeChunkList *pCodeChunkList) |
||
148 | { |
||
149 | pCodeChunkList->RealLen = |
||
150 | pCodeChunkList->AllocLen = 0; |
||
151 | pCodeChunkList->Chunks = NULL; |
||
152 | } |
||
153 | |||
154 | int MoveCodeChunkToList(tCodeChunkList *pCodeChunkList, tCodeChunk *pNewCodeChunk, Boolean WarnOverlap) |
||
155 | { |
||
156 | unsigned Index; |
||
157 | |||
158 | /* increase size? */ |
||
159 | |||
160 | if (pCodeChunkList->RealLen >= pCodeChunkList->AllocLen) |
||
161 | { |
||
162 | int Res = SetCodeChunkListAllocLen(pCodeChunkList, pCodeChunkList->RealLen + 16); |
||
163 | |||
164 | if (Res) |
||
165 | return Res; |
||
166 | } |
||
167 | |||
168 | /* find sort in position */ |
||
169 | |||
170 | for (Index = 0; Index < pCodeChunkList->RealLen; Index++) |
||
171 | if (pCodeChunkList->Chunks[Index].Start > pNewCodeChunk->Start) |
||
172 | break; |
||
173 | |||
174 | /* sort in */ |
||
175 | |||
176 | memmove(pCodeChunkList->Chunks + Index + 1, |
||
177 | pCodeChunkList->Chunks + Index, |
||
178 | sizeof(*pCodeChunkList->Chunks) * (pCodeChunkList->RealLen - Index)); |
||
179 | pCodeChunkList->Chunks[Index] = *pNewCodeChunk; |
||
180 | pCodeChunkList->RealLen++; |
||
181 | |||
182 | /* data was moved out of chunk */ |
||
183 | |||
184 | InitCodeChunk(pNewCodeChunk); |
||
185 | |||
186 | /* check overlap? */ |
||
187 | |||
188 | if (WarnOverlap) |
||
189 | { |
||
190 | if (Index > 0) |
||
191 | CheckOverlap(pCodeChunkList->Chunks + Index - 1, |
||
192 | pCodeChunkList->Chunks + Index); |
||
193 | if (Index < pCodeChunkList->RealLen - 1U) |
||
194 | CheckOverlap(pCodeChunkList->Chunks + Index, |
||
195 | pCodeChunkList->Chunks + Index + 1); |
||
196 | } |
||
197 | |||
198 | return 0; |
||
199 | } |
||
200 | |||
201 | extern void FreeCodeChunkList(tCodeChunkList *pCodeChunkList) |
||
202 | { |
||
203 | SetCodeChunkListAllocLen(pCodeChunkList, 0); |
||
204 | } |
||
205 | |||
206 | Boolean RetrieveCodeFromChunkList(const tCodeChunkList *pCodeChunkList, LargeWord Start, Byte *pData, unsigned Count) |
||
207 | { |
||
208 | const tCodeChunk *pChunk; |
||
209 | LargeWord OverlapStart, OverlapEnd; |
||
210 | Boolean Found; |
||
211 | |||
212 | while (Count > 0) |
||
213 | { |
||
214 | Found = False; |
||
215 | for (pChunk = pCodeChunkList->Chunks; pChunk < pCodeChunkList->Chunks + pCodeChunkList->RealLen; pChunk++) |
||
216 | { |
||
217 | OverlapStart = max(pChunk->Start, Start); |
||
218 | OverlapEnd = min(pChunk->Start + pChunk->Length - 1, Start + Count - 1); |
||
219 | if (OverlapStart <= OverlapEnd) |
||
220 | { |
||
221 | unsigned PartLength = OverlapEnd - OverlapStart + 1; |
||
222 | |||
223 | memcpy(pData, pChunk->pCode + (OverlapStart - pChunk->Start), PartLength); |
||
224 | pData += PartLength; |
||
225 | Count -= PartLength; |
||
226 | Found = True; |
||
227 | break; |
||
228 | } |
||
229 | } |
||
230 | if (!Found) |
||
231 | return False; |
||
232 | } |
||
233 | return True; |
||
234 | } |
||
235 | |||
236 | LargeWord GetCodeChunksStored(const tCodeChunkList *pCodeChunkList) |
||
237 | { |
||
238 | LargeWord Sum = 0; |
||
239 | const tCodeChunk *pChunk; |
||
240 | |||
241 | for (pChunk = pCodeChunkList->Chunks; pChunk < pCodeChunkList->Chunks + pCodeChunkList->RealLen; pChunk++) |
||
242 | Sum += pChunk->Length; |
||
243 | |||
244 | return Sum; |
||
245 | } |