Subversion Repositories pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

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