/* asmrelocs.c */
/****************************************************************************/
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */
/* */
/* AS-Portierung */
/* */
/* Verwaltung von Relokationslisten */
/* */
/* Historie: 25. 7.1999 Grundsteinlegung */
/* 1. 8.1999 Merge-Funktion implementiert */
/* 8. 8.1999 Reloc-Liste gespeichert */
/* 15. 9.1999 fehlende Includes */
/* Add in Merge */
/* 19. 1.2000 TransferRelocs begonnen */
/* 8. 3.2000 'ambigious else'-Warnungen beseitigt */
/* 30.10.2000 added transfer of arbitrary lists */
/* */
/****************************************************************************/
#include "stdinc.h"
#include <string.h>
#include "strutil.h"
#include "asmdef.h"
#include "asmsub.h"
#include "asmcode.h"
#include "asmrelocs.h"
#include "errmsg.h"
#include "fileformat.h"
/*---------------------------------------------------------------------------*/
PRelocEntry LastRelocs = NULL;
/*---------------------------------------------------------------------------*/
PRelocEntry MergeRelocs(PRelocEntry *list1, PRelocEntry *list2, Boolean Add)
{
PRelocEntry PRun1, PRun2, PPrev, PNext, PLast, PRes;
PRun1 = *list1;
PLast = PRes = NULL;
/* ueber alle in Liste 1 */
while (PRun1)
{
/* Uebereinstimmung suchen, die sich aufhebt */
PNext = PRun1->Next;
PRun2 = *list2;
PPrev = NULL;
while (PRun2)
if ((!as_strcasecmp(PRun1->Ref, PRun2->Ref)) && ((PRun1->Add != PRun2->Add) != Add))
{
/* gefunden -> beide weg */
if (!PPrev)
*list2 = PRun2->Next;
else
PPrev->Next = PRun2->Next;
PRun1 = NULL;
break;
}
else
{
PPrev = PRun2;
PRun2 = PRun2->Next;
}
/* ansonsten an Ergebnisliste anhaengen */
if (PRun1)
{
if (!PLast)
PRes = PLast = PRun1;
else
{
PLast->Next = PRun1;
PLast = PRun1;
}
}
PRun1 = PNext;
}
/* Reste aus Liste 2 nicht vergessen */
if (!PLast)
PRes = *list2;
else
PLast->Next = *list2;
/* Quellisten jetzt leer */
*list1 = *list2 = NULL;
/* fertich */
return PRes;
}
void InvertRelocs(PRelocEntry *erg, PRelocEntry *src)
{
PRelocEntry SRun;
for (SRun = *src; SRun; SRun = SRun->Next)
SRun->Add = !(SRun->Add);
*erg = *src;
}
void FreeRelocs(PRelocEntry *list)
{
PRelocEntry Run;
while (*list)
{
Run = *list;
*list = (*list)->Next;
}
}
PRelocEntry DupRelocs(PRelocEntry src)
{
PRelocEntry First, Run, SRun, Neu;
First = Run = NULL;
for (SRun = src; SRun; SRun = SRun->Next)
{
Neu
= (PRelocEntry
) malloc(sizeof(TRelocEntry
));
Neu->Next = NULL;
Neu->Ref = as_strdup(SRun->Ref);
Neu->Add = SRun->Add;
if (!First)
First = Neu;
else
Run->Next = Neu;
Run = Neu;
}
return First;
}
void SetRelocs(PRelocEntry List)
{
if (LastRelocs)
{
WrError(ErrNum_UnresRelocs);
FreeRelocs(&LastRelocs);
}
LastRelocs = List;
}
void TransferRelocs2(PRelocEntry RelocList, LargeWord Addr, LongWord Type)
{
PPatchEntry NewPatch;
PRelocEntry Curr;
while (RelocList)
{
Curr = RelocList;
NewPatch
= (PPatchEntry
) malloc(sizeof(TPatchEntry
));
NewPatch->Next = NULL;
NewPatch->Address = Addr;
NewPatch->Ref = Curr->Ref;
NewPatch->RelocType = Type;
if (!Curr->Add)
NewPatch->RelocType |= RelocFlagSUB;
if (PatchLast == NULL)
PatchList = NewPatch;
else
PatchLast->Next = NewPatch;
PatchLast = NewPatch;
RelocList = Curr->Next;
}
}
void TransferRelocs(LargeWord Addr, LongWord Type)
{
TransferRelocs2(LastRelocs, Addr, Type);
LastRelocs = NULL;
}
void SubPCRefReloc(void)
{
PRelocEntry Run, Prev, New;
if (!RelSegs)
return;
/* search if PC subtraction evens out against an addition */
for (Prev = NULL, Run = LastRelocs; Run; Prev = Run, Run = Run->Next)
if ((Run
->Add
) && (!strcmp(Run
->Ref
, RelName_SegStart
)))
{
if (Prev)
Prev->Next = Run->Next;
else
LastRelocs = Run->Next;
return;
}
/* in case we did not find one, add a new one */
New
= (PRelocEntry
) malloc(sizeof(TRelocEntry
));
New->Ref = as_strdup(RelName_SegStart);
New->Add = FALSE;
New->Next = NULL;
if (Prev)
Prev->Next = New;
else
LastRelocs = New;
}
void AddExport(char *Name, LargeInt Value, LongWord Flags)
{
PExportEntry PNew;
PNew
= (PExportEntry
) malloc(sizeof(TExportEntry
));
PNew->Next = NULL;
PNew->Name = as_strdup(Name);
PNew->Value = Value;
PNew->Flags = Flags;
if (!ExportList)
ExportList = PNew;
else
ExportLast->Next = PNew;
ExportLast = PNew;
}