Subversion Repositories pentevo

Rev

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

  1. /* asmcode.c */
  2. /*****************************************************************************/
  3. /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
  4. /*                                                                           */
  5. /* AS-Portierung                                                             */
  6. /*                                                                           */
  7. /* Verwaltung der Code-Datei                                                 */
  8. /*                                                                           */
  9. /*****************************************************************************/
  10.  
  11. #include "stdinc.h"
  12. #include <string.h>
  13.  
  14. #include "version.h"
  15. #include "be_le.h"
  16. #include "chunks.h"
  17. #include "as.h"
  18. #include "asmdef.h"
  19. #include "errmsg.h"
  20. #include "strutil.h"
  21. #include "asmsub.h"
  22. #include "asmpars.h"
  23. #include "asmrelocs.h"
  24. #include "asmlist.h"
  25. #include "asmlabel.h"
  26.  
  27. #include "asmcode.h"
  28.  
  29. #define CodeBufferSize 512
  30.  
  31. static Word LenSoFar;
  32. static LongInt RecPos, LenPos;
  33. static Boolean ThisRel;
  34.  
  35. static Word CodeBufferFill;
  36. static Byte *CodeBuffer;
  37.  
  38. PPatchEntry PatchList, PatchLast;
  39. PExportEntry ExportList, ExportLast;
  40. LongInt SectSymbolCounter;
  41. String SectSymbolName;
  42.  
  43. static void FlushBuffer(void)
  44. {
  45.   if (CodeBufferFill > 0)
  46.   {
  47.     if (fwrite(CodeBuffer, 1, CodeBufferFill, PrgFile) != CodeBufferFill)
  48.       ChkIO(ErrNum_FileWriteError);
  49.     CodeBufferFill = 0;
  50.   }
  51. }
  52.  
  53. void DreheCodes(void)
  54. {
  55.   int z;
  56.   LongInt l = CodeLen * Granularity();
  57.  
  58.   switch (ActListGran)
  59.   {
  60.     case 2:
  61.       for (z = 0; z < l >> 1; z++)
  62.         WAsmCode[z] = ((WAsmCode[z] & 0xff) << 8) + ((WAsmCode[z] & 0xff00) >> 8);
  63.       break;
  64.     case 4:
  65.       for (z = 0; z < l >> 2; z++)
  66.       {
  67.         LongWord Dest;
  68.         int z2;
  69.  
  70.         for (z2 = 0, Dest = 0; z2 < 4; z2++)
  71.         {
  72.           Dest = (Dest << 8) | (DAsmCode[z] & 0xff);
  73.           DAsmCode[z] >>= 8;
  74.         }
  75.         DAsmCode[z] = Dest;
  76.       }
  77.       break;
  78.   }
  79. }
  80.  
  81. static void WrPatches(void)
  82. {
  83.   LongWord Cnt, ExportCnt, StrLen;
  84.   Byte T8;
  85.  
  86.   if (PatchList || ExportList)
  87.   {
  88.     /* find out length of string field */
  89.  
  90.     Cnt = StrLen = 0;
  91.     for (PatchLast = PatchList; PatchLast; PatchLast = PatchLast->Next)
  92.     {
  93.       Cnt++;
  94.       StrLen += (PatchLast->len = strlen(PatchLast->Ref) + 1);
  95.     }
  96.     ExportCnt = 0;
  97.     for (ExportLast = ExportList; ExportLast; ExportLast = ExportLast->Next)
  98.     {
  99.       ExportCnt++;
  100.       StrLen += (ExportLast->len = strlen(ExportLast->Name) + 1);
  101.     }
  102.  
  103.     /* write header */
  104.  
  105.     T8 = FileHeaderRelocInfo;
  106.     if (fwrite(&T8, 1, 1, PrgFile) != 1) ChkIO(ErrNum_FileWriteError);
  107.     if (!Write4(PrgFile, &Cnt)) ChkIO(ErrNum_FileWriteError);
  108.     if (!Write4(PrgFile, &ExportCnt)) ChkIO(ErrNum_FileWriteError);
  109.     if (!Write4(PrgFile, &StrLen)) ChkIO(ErrNum_FileWriteError);
  110.  
  111.     /* write patch entries */
  112.  
  113.     StrLen = 0;
  114.     for (PatchLast = PatchList; PatchLast; PatchLast = PatchLast->Next)
  115.     {
  116.       if (!Write8(PrgFile, &(PatchLast->Address))) ChkIO(ErrNum_FileWriteError);
  117.       if (!Write4(PrgFile, &StrLen)) ChkIO(ErrNum_FileWriteError);
  118.       if (!Write4(PrgFile, &(PatchLast->RelocType))) ChkIO(ErrNum_FileWriteError);
  119.       StrLen += PatchLast->len;
  120.     }
  121.  
  122.     /* write export entries */
  123.  
  124.     for (ExportLast = ExportList; ExportLast; ExportLast = ExportLast->Next)
  125.     {
  126.       if (!Write4(PrgFile, &StrLen)) ChkIO(ErrNum_FileWriteError);
  127.       if (!Write4(PrgFile, &(ExportLast->Flags))) ChkIO(ErrNum_FileWriteError);
  128.       if (!Write8(PrgFile, &(ExportLast->Value))) ChkIO(ErrNum_FileWriteError);
  129.       StrLen += ExportLast->len;
  130.     }
  131.  
  132.     /* write string table, free structures */
  133.  
  134.     while (PatchList)
  135.     {
  136.       PatchLast = PatchList;
  137.       if (fwrite(PatchLast->Ref, 1, PatchLast->len, PrgFile) != PatchLast->len) ChkIO(ErrNum_FileWriteError);
  138.       free(PatchLast->Ref);
  139.       PatchList = PatchLast->Next;
  140.       free(PatchLast);
  141.     }
  142.     PatchLast = NULL;
  143.  
  144.     while (ExportList)
  145.     {
  146.       ExportLast = ExportList;
  147.       if (fwrite(ExportLast->Name, 1, ExportLast->len, PrgFile) != ExportLast->len) ChkIO(ErrNum_FileWriteError);
  148.       free(ExportLast->Name);
  149.       ExportList = ExportLast->Next;
  150.       free(ExportLast);
  151.     }
  152.     ExportLast = NULL;
  153.   }
  154. }
  155.  
  156. /*--- neuen Record in Codedatei anlegen.  War der bisherige leer, so wird ---
  157.  ---- dieser ueberschrieben. ------------------------------------------------*/
  158.  
  159. static void WrRecHeader(void)
  160. {
  161.   Byte b;
  162.  
  163.   /* assume simple record without relocation info */
  164.  
  165.   ThisRel = RelSegs;
  166.   b = ThisRel ? FileHeaderRelocRec : FileHeaderDataRec;
  167.   if (fwrite(&b, 1, 1, PrgFile) != 1) ChkIO(ErrNum_FileWriteError);
  168.   if (fwrite(&HeaderID, 1, 1, PrgFile) != 1) ChkIO(ErrNum_FileWriteError);
  169.   b = ActPC; if (fwrite(&b, 1, 1, PrgFile) != 1) ChkIO(ErrNum_FileWriteError);
  170.   b = Grans[ActPC]; if (fwrite(&b, 1, 1, PrgFile) != 1) ChkIO(ErrNum_FileWriteError);
  171.   fflush(PrgFile);
  172. }
  173.  
  174. void NewRecord(LargeWord NStart)
  175. {
  176.   LongInt h;
  177.   LongWord PC;
  178.   Byte Header;
  179.  
  180.   /* flush remaining code in buffer */
  181.  
  182.   FlushBuffer();
  183.  
  184.   /* zero length record which may be deleted ? */
  185.   /* do not write out patches at this place - they
  186.      will be merged with the next record. */
  187.  
  188.   if (LenSoFar == 0)
  189.   {
  190.     if (fseek(PrgFile, RecPos, SEEK_SET) != 0) ChkIO(ErrNum_FileReadError);
  191.     WrRecHeader();
  192.     h = NStart;
  193.     if (!Write4(PrgFile, &h)) ChkIO(ErrNum_FileWriteError);
  194.     LenPos = ftell(PrgFile);
  195.     if (!Write2(PrgFile, &LenSoFar)) ChkIO(ErrNum_FileWriteError);
  196.   }
  197.  
  198.   /* otherwise full record */
  199.  
  200.   else
  201.   {
  202.     /* store current position (=end of file) */
  203.  
  204.     h = ftell(PrgFile);
  205.  
  206.     /* do we have reloc. info? - then change record type */
  207.  
  208.     if (PatchList || ExportList)
  209.     {
  210.       fflush(PrgFile);
  211.       if (fseek(PrgFile, RecPos, SEEK_SET) != 0) ChkIO(ErrNum_FileReadError);
  212.       Header = ThisRel ? FileHeaderRRelocRec : FileHeaderRDataRec;
  213.       if (fwrite(&Header, 1, 1, PrgFile) != 1) ChkIO(ErrNum_FileWriteError);
  214.     }
  215.  
  216.     /* fill in length of record */
  217.  
  218.     fflush(PrgFile);
  219.     if (fseek(PrgFile, LenPos, SEEK_SET) != 0) ChkIO(ErrNum_FileReadError);
  220.     if (!Write2(PrgFile, &LenSoFar)) ChkIO(ErrNum_FileWriteError);
  221.  
  222.     /* go back to end of file */
  223.  
  224.     if (fseek(PrgFile, h, SEEK_SET) != 0) ChkIO(ErrNum_FileReadError);
  225.  
  226.     /* write out reloc info */
  227.  
  228.     WrPatches();
  229.  
  230.     /* store begin of new code record */
  231.  
  232.     RecPos = ftell(PrgFile);
  233.  
  234.     LenSoFar = 0;
  235.     WrRecHeader();
  236.     ThisRel = RelSegs;
  237.     PC = NStart;
  238.     if (!Write4(PrgFile, &PC)) ChkIO(ErrNum_FileWriteError);
  239.     LenPos = ftell(PrgFile);
  240.     if (!Write2(PrgFile, &LenSoFar)) ChkIO(ErrNum_FileWriteError);
  241.   }
  242. #if 0
  243.   /* put in the hidden symbol for the relocatable segment ? */
  244.  
  245.   if ((RelSegs) && (strcmp(CurrFileName, "INTERNAL")))
  246.   {
  247.     as_snprintf(SectSymbolName, sizeof(SectSymbolName), "__%s_%d",
  248.                 NamePart(CurrFileName), (int)(SectSymbolCounter++));
  249.     AddExport(SectSymbolName, ProgCounter());
  250.   }
  251. #endif
  252. }
  253.  
  254. /*--- Codedatei eroeffnen --------------------------------------------------*/
  255.  
  256. void OpenFile(void)
  257. {
  258.   Word h;
  259.  
  260.   errno = 0;
  261.   PrgFile = fopen(OutName, OPENWRMODE);
  262.   if (!PrgFile)
  263.     ChkXIO(ErrNum_OpeningFile, OutName);
  264.  
  265.   errno = 0;
  266.   h = FileMagic;
  267.   if (!Write2(PrgFile,&h)) ChkIO(ErrNum_FileWriteError);
  268.  
  269.   CodeBufferFill = 0;
  270.   RecPos = ftell(PrgFile);
  271.   LenSoFar = 0;
  272.   NewRecord(PCs[ActPC]);
  273. }
  274.  
  275. /*---- Codedatei schliessen -------------------------------------------------*/
  276.  
  277. void CloseFile(void)
  278. {
  279.   Byte Head;
  280.   String h;
  281.   LongWord Adr;
  282.  
  283.   as_snprintf(h, sizeof(h), "AS %s/%s-%s", Version, ARCHPRNAME, ARCHSYSNAME);
  284.  
  285.   NewRecord(PCs[ActPC]);
  286.   fseek(PrgFile, RecPos, SEEK_SET);
  287.  
  288.   if (StartAdrPresent)
  289.   {
  290.     Head = FileHeaderStartAdr;
  291.     if (fwrite(&Head,sizeof(Head), 1, PrgFile) != 1) ChkIO(ErrNum_FileWriteError);
  292.     Adr = StartAdr;
  293.     if (!Write4(PrgFile,&Adr)) ChkIO(ErrNum_FileWriteError);
  294.   }
  295.  
  296.   Head = FileHeaderEnd;
  297.   if (fwrite(&Head,sizeof(Head), 1, PrgFile) != 1) ChkIO(ErrNum_FileWriteError);
  298.   if (fwrite(h, 1, strlen(h), PrgFile) != strlen(h)) ChkIO(ErrNum_FileWriteError);
  299.   fclose(PrgFile);
  300.   if (Magic)
  301.     unlink(OutName);
  302. }
  303.  
  304. /*--- erzeugten Code einer Zeile in Datei ablegen ---------------------------*/
  305.  
  306. void WriteBytes(void)
  307. {
  308.   Word ErgLen;
  309.  
  310.   if (CodeLen == 0)
  311.     return;
  312.   ErgLen = CodeLen * Granularity();
  313.   if ((TurnWords != 0) != (HostBigEndian != 0))
  314.     DreheCodes();
  315.   if (((LongInt)LenSoFar) + ((LongInt)ErgLen) > 0xffff)
  316.     NewRecord(PCs[ActPC]);
  317.   if (CodeBufferFill + ErgLen < CodeBufferSize)
  318.   {
  319.     memcpy(CodeBuffer + CodeBufferFill, BAsmCode, ErgLen);
  320.     CodeBufferFill += ErgLen;
  321.   }
  322.   else
  323.   {
  324.     FlushBuffer();
  325.     if (ErgLen < CodeBufferSize)
  326.     {
  327.       memcpy(CodeBuffer, BAsmCode, ErgLen);
  328.       CodeBufferFill = ErgLen;
  329.     }
  330.     else if (fwrite(BAsmCode, 1, ErgLen, PrgFile) != ErgLen)
  331.       ChkIO(ErrNum_FileWriteError);
  332.   }
  333.   LenSoFar += ErgLen;
  334.   if ((TurnWords != 0) != (HostBigEndian != 0))
  335.     DreheCodes();
  336. }
  337.  
  338. void RetractWords(Word Cnt)
  339. {
  340.   Word ErgLen;
  341.  
  342.   ErgLen = Cnt * Granularity();
  343.   if (LenSoFar < ErgLen)
  344.   {
  345.     WrError(ErrNum_ParNotPossible);
  346.     return;
  347.   }
  348.  
  349.   if (MakeUseList)
  350.     DeleteChunk(SegChunks + ActPC, ProgCounter() - Cnt, Cnt);
  351.  
  352.   PCs[ActPC] -= Cnt;
  353.  
  354.   if (CodeBufferFill >= ErgLen)
  355.     CodeBufferFill -= ErgLen;
  356.   else
  357.   {
  358.     if (fseek(PrgFile, -(ErgLen - CodeBufferFill), SEEK_CUR) == -1)
  359.       ChkIO(ErrNum_FileWriteError);
  360.     CodeBufferFill = 0;
  361.   }
  362.  
  363.   LenSoFar -= ErgLen;
  364.  
  365.   Retracted = True;
  366. }
  367.  
  368. /*!------------------------------------------------------------------------
  369.  * \fn     InsertPadding(unsigned NumBytes, Boolean OnlyReserve)
  370.  * \brief  insert padding bytes into code
  371.  * \param  NumBytes # of bytes to add
  372.  * \param  OnlyReserve write code or only reserve?
  373.  * ------------------------------------------------------------------------ */
  374.  
  375. void InsertPadding(unsigned NumBytes, Boolean OnlyReserve)
  376. {
  377.   Boolean SaveDontPrint = DontPrint;
  378.   LargeWord OldValue = EProgCounter();
  379.  
  380.   /* write/reserve code */
  381.  
  382.   SetMaxCodeLen(NumBytes);
  383.   DontPrint = OnlyReserve;
  384.   memset(BAsmCode, 0, CodeLen = NumBytes);
  385.   WriteCode();
  386.   MakeList("<padding>");
  387.  
  388.   /* fix up possible label value so it points to the actual code */
  389.  
  390.   LabelModify(OldValue, EProgCounter());
  391.  
  392.   CodeLen = 0;
  393.   DontPrint = SaveDontPrint;
  394. }
  395.  
  396. /*!------------------------------------------------------------------------
  397.  * \fn     indir_split_pos(const char * p_arg)
  398.  * \brief  find separator for next component in a (x+y-z..) construct
  399.  * \param  p_arg (remaining) source argument
  400.  * \return split position for next component or NULL if no more split character
  401.  * ------------------------------------------------------------------------ */
  402.  
  403. char *indir_split_pos(const char *p_arg)
  404. {
  405.   char *p_split_pos = QuotMultPos(p_arg, "+-");
  406.  
  407.   /* Sequence of up to three +/- has special meaning for local symbols: */
  408.  
  409.   if (p_split_pos == p_arg)
  410.   {
  411.     int z;
  412.     Boolean same = True;
  413.     for (z = 1; p_split_pos[z] && (z < LOCSYMSIGHT); z++)
  414.       if (p_split_pos[z] != p_split_pos[0])
  415.       {
  416.         same = False;
  417.         break;
  418.       }
  419.     if (!p_split_pos[z] && same)
  420.       p_split_pos = NULL;
  421.   }
  422.   return p_split_pos;
  423. }
  424.  
  425. void asmcode_init(void)
  426. {
  427.   PatchList = PatchLast = NULL;
  428.   ExportList = ExportLast = NULL;
  429.   CodeBuffer = (Byte*) malloc(sizeof(Byte) * (CodeBufferSize + 1));
  430. }
  431.