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 | } |