Пример #1
0
void ObjReadData (FILE* F, ObjData* O)
/* Read object file data from the given file. The function expects the Name
 * and Start fields to be valid. Header and basic data are read.
 */
{
    unsigned long Count;

    /* Seek to the start of the object file data */
    fseek (F, O->Start, SEEK_SET);

    /* Read the object file header */
    ObjReadHeader (F, &O->Header, O->Name);

    /* Read the string pool */
    fseek (F, O->Start + O->Header.StrPoolOffs, SEEK_SET);
    Count = ReadVar (F);
    CollGrow (&O->Strings, Count);
    while (Count--) {
        CollAppend (&O->Strings, ReadStr (F));
    }

    /* Read the exports */
    fseek (F, O->Start + O->Header.ExportOffs, SEEK_SET);
    Count = ReadVar (F);
    CollGrow (&O->Exports, Count);
    while (Count--) {

        unsigned char ConDes[CD_TYPE_COUNT];

        /* Skip data until we get to the name */
        unsigned Type = ReadVar (F);
        (void) Read8 (F);       /* AddrSize */
        ReadData (F, ConDes, SYM_GET_CONDES_COUNT (Type));

        /* Now this is what we actually need: The name of the export */
        CollAppend (&O->Exports, CollAt (&O->Strings, ReadVar (F)));

        /* Skip the export value */
        if (SYM_IS_EXPR (Type)) {
            /* Expression tree */
            SkipExpr (F);
        } else {
            /* Literal value */
            (void) Read32 (F);
        }

        /* Skip the size if necessary */
        if (SYM_HAS_SIZE (Type)) {
            (void) ReadVar (F);
        }

        /* Line info indices */
        SkipLineInfoList (F);
        SkipLineInfoList (F);
    }
}
Пример #2
0
static Segment* NewSegFromDef (SegDef* Def)
/* Create a new segment from a segment definition. Used only internally, no
 * checks.
 */
{
    /* Create a new segment */
    Segment* S = xmalloc (sizeof (*S));

    /* Initialize it */
    S->Root      = 0;
    S->Last      = 0;
    S->FragCount = 0;
    S->Num       = CollCount (&SegmentList);
    S->Flags     = SEG_FLAG_NONE;
    S->Align     = 1;
    S->RelocMode = 1;
    S->PC        = 0;
    S->AbsPC     = 0;
    S->Def       = Def;

    /* Insert it into the segment list */
    CollAppend (&SegmentList, S);

    /* And return it... */
    return S;
}
Пример #3
0
CodeLabel* CS_AddLabel (CodeSeg* S, const char* Name)
/* Add a code label for the next instruction to follow */
{
    /* Calculate the hash from the name */
    unsigned Hash = HashStr (Name) % CS_LABEL_HASH_SIZE;

    /* Try to find the code label if it does already exist */
    CodeLabel* L = CS_FindLabel (S, Name, Hash);

    /* Did we find it? */
    if (L) {
     	/* We found it - be sure it does not already have an owner */
    	if (L->Owner) {
       	    Error ("ASM label `%s' is already defined", Name);
            return L;
    	}
    } else {
     	/* Not found - create a new one */
     	L = CS_NewCodeLabel (S, Name, Hash);
    }

    /* Safety. This call is quite costly, but safety is better */
    if (CollIndex (&S->Labels, L) >= 0) {
       	Error ("ASM label `%s' is already defined", Name);
        return L;
    }

    /* We do now have a valid label. Remember it for later */
    CollAppend (&S->Labels, L);

    /* Return the label */
    return L;
}
Пример #4
0
Section* NewSection (Segment* Seg, unsigned long Alignment, unsigned char AddrSize)
/* Create a new section for the given segment */
{
    /* Allocate memory */
    Section* S = xmalloc (sizeof (Section));

    /* Initialize the data */
    S->Next     = 0;
    S->Seg      = Seg;
    S->Obj      = 0;
    S->FragRoot = 0;
    S->FragLast = 0;
    S->Size     = 0;
    S->Alignment= Alignment;
    S->AddrSize = AddrSize;

    /* Calculate the alignment bytes needed for the section */
    S->Fill = AlignCount (Seg->Size, S->Alignment);

    /* Adjust the segment size and set the section offset */
    Seg->Size  += S->Fill;
    S->Offs     = Seg->Size;    /* Current size is offset */

    /* Insert the section into the segment */
    CollAppend (&Seg->Sections, S);

    /* Return the struct */
    return S;
}
Пример #5
0
CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg,
                         CodeLabel* JumpTo, LineInfo* LI)
/* Create a new code entry, initialize and return it */
{
    /* Get the opcode description */
    const OPCDesc* D = GetOPCDesc (OPC);

    /* Allocate memory */
    CodeEntry* E = xmalloc (sizeof (CodeEntry));

    /* Initialize the fields */
    E->OPC    = D->OPC;
    E->AM     = AM;
    E->Size   = GetInsnSize (E->OPC, E->AM);
    E->Arg    = GetArgCopy (Arg);
    E->Flags  = NumArg (E->Arg, &E->Num)? CEF_NUMARG : 0;   /* Needs E->Arg */
    E->Info   = D->Info;
    E->JumpTo = JumpTo;
    E->LI     = UseLineInfo (LI);
    E->RI     = 0;
    SetUseChgInfo (E, D);
    InitCollection (&E->Labels);

    /* If we have a label given, add this entry to the label */
    if (JumpTo) {
        CollAppend (&JumpTo->JumpFrom, E);
    }

    /* Return the initialized struct */
    return E;
}
Пример #6
0
static O65Data* ReadO65Data (FILE* F)
/* Read a complete o65 file into dynamically allocated memory and return the
 * created O65Data struct.
 */
{
    unsigned long Count;
    O65Option* O;

    /* Create the struct we're going to return */
    O65Data* D = NewO65Data ();

    /* Read the header */
    ReadO65Header (F, &D->Header);

    /* Read the options */
    while ((O = ReadO65Option (F)) != 0) {
        CollAppend (&D->Options, O);
    }

    /* Allocate space for the text segment and read it */
    D->Text = xmalloc (D->Header.tlen);
    ReadData (F, D->Text, D->Header.tlen);

    /* Allocate space for the data segment and read it */
    D->Data = xmalloc (D->Header.dlen);
    ReadData (F, D->Data, D->Header.dlen);

    /* Read the undefined references list */
    Count = ReadO65Size (F, &D->Header);
    while (Count--) {
        CollAppend (&D->Imports, ReadO65Import (F));
    }

    /* Read the relocation tables for text and data segment */
    ReadO65RelocInfo (F, D, &D->TextReloc);
    ReadO65RelocInfo (F, D, &D->DataReloc);

    /* Read the exported globals list */
    Count = ReadO65Size (F, &D->Header);
    while (Count--) {
        CollAppend (&D->Exports, ReadO65Export (F, &D->Header));
    }

    /* Return the o65 data read from the file */
    return D;
}
Пример #7
0
void CS_AddEntry (CodeSeg* S, struct CodeEntry* E)
/* Add an entry to the given code segment */
{
    /* Transfer the labels if we have any */
    CS_MoveLabelsToEntry (S, E);

    /* Add the entry to the list of code entries in this segment */
    CollAppend (&S->Entries, E);
}
Пример #8
0
static void AddAttr (Declaration* D, DeclAttr* A)
/* Add an attribute to a declaration */
{
    /* Allocate the list if necessary, the add the attribute */
    if (D->Attributes == 0) {
        D->Attributes = NewCollection ();
    }
    CollAppend (D->Attributes, A);
}
Пример #9
0
void SymRef (SymEntry* S)
/* Mark the given symbol as referenced */
{
    /* Mark the symbol as referenced */
    S->Flags |= SF_REFERENCED;

    /* Remember the current location */
    CollAppend (&S->RefLines, GetAsmLineInfo ());
}
Пример #10
0
void CE_AttachLabel (CodeEntry* E, CodeLabel* L)
/* Attach the label to the entry */
{
    /* Add it to the entries label list */
    CollAppend (&E->Labels, L);

    /* Tell the label about it's owner */
    L->Owner = E;
}
Пример #11
0
static AFile* NewAFile (IFile* IF, FILE* F)
/* Create a new AFile, push it onto the stack, add the path of the file to
 * the path search list, and finally return a pointer to the new AFile struct.
 */
{
    StrBuf Path = AUTO_STRBUF_INITIALIZER;

    /* Allocate a AFile structure */
    AFile* AF = (AFile*) xmalloc (sizeof (AFile));

    /* Initialize the fields */
    AF->Line  = 0;
    AF->F     = F;
    AF->Input = IF;

    /* Increment the usage counter of the corresponding IFile. If this
     * is the first use, set the file data and output debug info if
     * requested.
     */
    if (IF->Usage++ == 0) {

 	/* Get file size and modification time. There a race condition here,
         * since we cannot use fileno() (non standard identifier in standard
         * header file), and therefore not fstat. When using stat with the
         * file name, there's a risk that the file was deleted and recreated
         * while it was open. Since mtime and size are only used to check
         * if a file has changed in the debugger, we will ignore this problem
         * here.
         */
     	struct stat Buf;
 	if (FileStat (IF->Name, &Buf) != 0) {
 	    /* Error */
 	    Fatal ("Cannot stat `%s': %s", IF->Name, strerror (errno));
 	}
       	IF->Size  = (unsigned long) Buf.st_size;
 	IF->MTime = (unsigned long) Buf.st_mtime;

 	/* Set the debug data */
 	g_fileinfo (IF->Name, IF->Size, IF->MTime);
    }

    /* Insert the new structure into the AFile collection */
    CollAppend (&AFiles, AF);

    /* Get the path of this file and add it as an extra search path.
     * To avoid file search overhead, we will add one path only once.
     * This is checked by the PushSearchPath function.
     */
    SB_CopyBuf (&Path, IF->Name, FindName (IF->Name) - IF->Name);
    SB_Terminate (&Path);
    AF->SearchPath = PushSearchPath (UsrIncSearchPath, SB_GetConstBuf (&Path));
    SB_Done (&Path);

    /* Return the new struct */
    return AF;
}
Пример #12
0
void CE_MoveLabel (CodeLabel* L, CodeEntry* E)
/* Move the code label L from it's former owner to the code entry E. */
{
    /* Delete the label from the owner */
    CollDeleteItem (&L->Owner->Labels, L);

    /* Set the new owner */
    CollAppend (&E->Labels, L);
    L->Owner = E;
}
Пример #13
0
void ReadStrPool (FILE* F, Collection* C)
/* Read a string pool from the current position into C. */
{
    /* The number of strings is the first item */
    unsigned long Count = ReadVar (F);

    /* Read all the strings into C */
    while (Count--) {
        CollAppend (C, ReadStr (F));
    }
}
Пример #14
0
static void CS_MoveLabelsToPool (CodeSeg* S, CodeEntry* E)
/* Move the labels of the code entry E to the label pool of the code segment */
{
    unsigned LabelCount = CE_GetLabelCount (E);
    while (LabelCount--) {
   	CodeLabel* L = CE_GetLabel (E, LabelCount);
	L->Owner = 0;
	CollAppend (&S->Labels, L);
    }
    CollDeleteAll (&E->Labels);
}
Пример #15
0
Segments* PushSegments (SymEntry* Func)
/* Make the new segment list current but remember the old one */
{
    /* Push the current pointer onto the stack */
    CollAppend (&SegmentStack, CS);

    /* Create a new Segments structure */
    CS = NewSegments (Func);

    /* Return the new struct */
    return CS;
}
Пример #16
0
static void ME_AppendActual (MacroExp* E, StrBuf* Arg)
/* Add a copy of Arg to the list of actual macro arguments.
 * NOTE: This function will clear Arg!
 */
{
    /* Create a new string buffer */
    StrBuf* A = NewStrBuf ();

    /* Move the contents of Arg to A */
    SB_Move (A, Arg);

    /* Add A to the actual arguments */
    CollAppend (&E->ActualArgs, A);
}
Пример #17
0
static ULabel* NewULabel (ExprNode* Val)
/* Create a new ULabel and insert it into the collection. The created label
 * structure is returned.
 */
{
    /* Allocate memory for the ULabel structure */
    ULabel* L = xmalloc (sizeof (ULabel));

    /* Initialize the fields */
    L->LineInfos = EmptyCollection;
    GetFullLineInfo (&L->LineInfos);
    L->Val       = Val;
    L->Ref       = 0;

    /* Insert the label into the collection */
    CollAppend (&ULabList, L);

    /* Return the created label */
    return L;
}
Пример #18
0
Assertion* ReadAssertion (FILE* F, struct ObjData* O)
/* Read an assertion from the given file */
{
    /* Allocate memory */
    Assertion* A = xmalloc (sizeof (Assertion));

    /* Read the fields from the file */
    A->LineInfos = EmptyCollection;
    A->Expr      = ReadExpr (F, O);
    A->Action    = (AssertAction) ReadVar (F);
    A->Msg       = MakeGlobalStringId (O, ReadVar (F));
    ReadLineInfoList (F, O, &A->LineInfos);

    /* Set remaining fields */
    A->Obj = O;

    /* Add the assertion to the global list */
    CollAppend (&Assertions, A);

    /* Return the new struct */
    return A;
}
Пример #19
0
ObjData* NewObjData (void)
/* Allocate a new structure on the heap, insert it into the list, return it */
{
    /* Allocate memory */
    ObjData* O = xmalloc (sizeof (ObjData));

    /* Initialize the data */
    O->Name        = 0;

    O->Flags       = 0;
    O->MTime       = 0;
    O->Start       = 0;
    O->Size        = 0;

    O->Strings     = EmptyCollection;
    O->Exports     = EmptyCollection;

    /* Add it to the list */
    CollAppend (&ObjPool, O);

    /* Return the new entry */
    return O;
}
Пример #20
0
static IFile* NewIFile (const char* Name, InputType Type)
/* Create and return a new IFile */
{
    /* Get the length of the name */
    unsigned Len = strlen (Name);

    /* Allocate a IFile structure */
    IFile* IF = (IFile*) xmalloc (sizeof (IFile) + Len);

    /* Initialize the fields */
    IF->Index = CollCount (&IFiles) + 1;
    IF->Usage = 0;
    IF->Size  = 0;
    IF->MTime = 0;
    IF->Type  = Type;
    memcpy (IF->Name, Name, Len+1);

    /* Insert the new structure into the IFile collection */
    CollAppend (&IFiles, IF);

    /* Return the new struct */
    return IF;
}
Пример #21
0
static Segment* NewSegment (unsigned Name, unsigned char AddrSize)
/* Create a new segment and initialize it */
{
    unsigned Hash;

    /* Allocate memory */
    Segment* S = xmalloc (sizeof (Segment));

    /* Initialize the fields */
    S->Name        = Name;
    S->Next        = 0;
    S->Flags       = SEG_FLAG_NONE;
    S->Sections    = EmptyCollection;
    S->MemArea     = 0;
    S->PC          = 0;
    S->Size        = 0;
    S->OutputName  = 0;
    S->OutputOffs  = 0;
    S->Alignment   = 1;
    S->FillVal     = 0;
    S->AddrSize    = AddrSize;
    S->ReadOnly    = 0;
    S->Dumped      = 0;

    /* Insert the segment into the segment list and assign the segment id */
    S->Id = CollCount (&SegmentList);
    CollAppend (&SegmentList, S);

    /* Insert the segment into the segment hash list */
    Hash = (S->Name & HASHTAB_MASK);
    S->Next = HashTab[Hash];
    HashTab[Hash] = S;

    /* Return the new entry */
    return S;
}
Пример #22
0
static FileEntry* NewFileEntry (unsigned Name, FileType Type,
                                unsigned long Size, unsigned long MTime)
/* Create a new FileEntry, insert it into the tables and return it */
{
    /* Allocate memory for the entry */
    FileEntry* F = xmalloc (sizeof (FileEntry));

    /* Initialize the fields */
    InitHashNode (&F->Node);
    F->Name     = Name;
    F->Index    = CollCount (&FileTab) + 1;     /* First file has index #1 */
    F->Type     = Type;
    F->Size     = Size;
    F->MTime    = MTime;

    /* Insert the file into the file table */
    CollAppend (&FileTab, F);

    /* Insert the entry into the hash table */
    HT_Insert (&HashTab, F);

    /* Return the new entry */
    return F;
}
Пример #23
0
void AddAssertion (ExprNode* Expr, AssertAction Action, unsigned Msg)
/* Add an assertion to the assertion table */
{
    /* Add an assertion object to the table */
    CollAppend (&Assertions, NewAssertion (Expr, Action, Msg));
}
Пример #24
0
void SymConDes (SymEntry* S, unsigned char AddrSize, unsigned Type, unsigned Prio)
/* Mark the given symbol as a module constructor/destructor. This will also
** mark the symbol as an export. Initializers may never be zero page symbols.
*/
{
    /* Check the parameters */
#if (CD_TYPE_MIN != 0)
    CHECK (Type >= CD_TYPE_MIN && Type <= CD_TYPE_MAX);
#else
    CHECK (Type <= CD_TYPE_MAX);
#endif
    CHECK (Prio >= CD_PRIO_MIN && Prio <= CD_PRIO_MAX);

    /* Check for errors */
    if (S->Flags & SF_IMPORT) {
        /* The symbol is already marked as imported external symbol */
        Error ("Symbol `%m%p' is already an import", GetSymName (S));
        return;
    }
    if (S->Flags & SF_VAR) {
        /* Variable symbols cannot be exported or imported */
        Error ("Var symbol `%m%p' cannot be exported", GetSymName (S));
        return;
    }

    /* If the symbol was already marked as an export or global, check if
    ** this was done specifiying the same address size. In case of a global
    ** declaration, silently remove the global flag.
    */
    if (S->Flags & (SF_EXPORT | SF_GLOBAL)) {
        if (S->ExportSize != AddrSize) {
            Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
        }
        S->Flags &= ~SF_GLOBAL;
    }
    S->ExportSize = AddrSize;

    /* If the symbol is already defined, check symbol size against the
    ** exported size.
    */
    if (S->Flags & SF_DEFINED) {
        if (S->ExportSize == ADDR_SIZE_DEFAULT) {
            /* Use the real size of the symbol */
            S->ExportSize = S->AddrSize;
        } else if (S->AddrSize != S->ExportSize) {
            Error ("Address size mismatch for symbol `%m%p'", GetSymName (S));
        }
    }

    /* If the symbol already was declared as a condes of this type,
    ** check if the new priority value is the same as the old one.
    */
    if (S->ConDesPrio[Type] != CD_PRIO_NONE) {
        if (S->ConDesPrio[Type] != Prio) {
            Error ("Redeclaration mismatch for symbol `%m%p'", GetSymName (S));
        }
    }
    S->ConDesPrio[Type] = Prio;

    /* Set the symbol data */
    S->Flags |= (SF_EXPORT | SF_REFERENCED);

    /* Remember the line info for this reference */
    CollAppend (&S->RefLines, GetAsmLineInfo ());
}
Пример #25
0
Export* ReadExport (FILE* F, ObjData* O)
/* Read an export from a file */
{
    unsigned    ConDesCount;
    unsigned    I;
    Export*     E;

    /* Read the type */
    unsigned Type = ReadVar (F);

    /* Read the address size */
    unsigned char AddrSize = Read8 (F);

    /* Create a new export without a name */
    E = NewExport (Type, AddrSize, INVALID_STRING_ID, O);

    /* Read the constructor/destructor decls if we have any */
    ConDesCount = SYM_GET_CONDES_COUNT (Type);
    if (ConDesCount > 0) {

        unsigned char ConDes[CD_TYPE_COUNT];

        /* Read the data into temp storage */
        ReadData (F, ConDes, ConDesCount);

        /* Re-order the data. In the file, each decl is encoded into a byte
        ** which contains the type and the priority. In memory, we will use
        ** an array of types which contain the priority.
        */
        for (I = 0; I < ConDesCount; ++I) {
            E->ConDes[CD_GET_TYPE (ConDes[I])] = CD_GET_PRIO (ConDes[I]);
        }
    }

    /* Read the name */
    E->Name = MakeGlobalStringId (O, ReadVar (F));

    /* Read the value */
    if (SYM_IS_EXPR (Type)) {
        E->Expr = ReadExpr (F, O);
    } else {
        E->Expr = LiteralExpr (Read32 (F), O);
    }

    /* Read the size */
    if (SYM_HAS_SIZE (Type)) {
        E->Size = ReadVar (F);
    }

    /* Last are the locations */
    ReadLineInfoList (F, O, &E->DefLines);
    ReadLineInfoList (F, O, &E->RefLines);

    /* If this symbol is exported as a condes, and the condes type declares a
    ** forced import, add this import to the object module.
    */
    for (I = 0; I < CD_TYPE_COUNT; ++I) {
        const ConDesImport* CDI;

        if (E->ConDes[I] != CD_PRIO_NONE && (CDI = ConDesGetImport (I)) != 0) {
            unsigned J;

            /* Generate a new import, and add it to the module's import list. */
            Import* Imp = GenImport (CDI->Name, CDI->AddrSize);

            Imp->Obj = O;
            CollAppend (&O->Imports, Imp);

            /* Add line info for the export that is actually the condes that
            ** forces the import.  Then, add line info for the config. file.
            ** The export's info is added first because the import pretends
            ** that it came from the object module instead of the config. file.
            */
            for (J = 0; J < CollCount (&E->DefLines); ++J) {
                CollAppend (&Imp->RefLines, DupLineInfo (CollAt (&E->DefLines, J)));
            }
            CollAppend (&Imp->RefLines, GenLineInfo (&CDI->Pos));
        }
    }

    /* Return the new export */
    return E;
}
Пример #26
0
int CE_UseLoadFlags (CodeEntry* E)
/* Return true if the instruction uses any flags that are set by a load of
** a register (N and Z).
*/
{
    /* Follow unconditional branches, but beware of endless loops. After this,
    ** E will point to the first entry that is not a branch.
    */
    if (E->Info & OF_UBRA) {
        Collection C = AUTO_COLLECTION_INITIALIZER;

        /* Follow the chain */
        while (E->Info & OF_UBRA) {

            /* Remember the entry so we can detect loops */
            CollAppend (&C, E);

            /* Check the target */
            if (E->JumpTo == 0 || CollIndex (&C, E->JumpTo->Owner) >= 0) {
                /* Unconditional jump to external symbol, or endless loop. */
                DoneCollection (&C);
                return 0;       /* Flags not used */
            }

            /* Follow the chain */
            E = E->JumpTo->Owner;
        }

        /* Delete the collection */
        DoneCollection (&C);
    }

    /* A branch will use the flags */
    if (E->Info & OF_FBRA) {
        return 1;
    }

    /* Call of a boolean transformer routine will also use the flags */
    if (E->OPC == OP65_JSR) {
        /* Get the condition that is evaluated and check it */
        switch (FindBoolCmpCond (E->Arg)) {
            case CMP_EQ:
            case CMP_NE:
            case CMP_GT:
            case CMP_GE:
            case CMP_LT:
            case CMP_LE:
            case CMP_UGT:
            case CMP_ULE:
                /* Will use the N or Z flags */
                return 1;


            case CMP_UGE:       /* Uses only carry */
            case CMP_ULT:       /* Dito */
            default:            /* No bool transformer subroutine */
                return 0;
        }
    }

    /* Anything else */
    return 0;
}
Пример #27
0
static void Add (SearchPaths* P, const char* New)
/* Cleanup a new search path and add it to the list */
{
    /* Add a clean copy of the path to the collection */
    CollAppend (P, CleanupPath (New));
}
Пример #28
0
void InsertObjData (ObjData* O)
/* Insert the ObjData object into the collection of used ObjData objects. */
{
    CollAppend (&ObjDataList, O);
}
Пример #29
0
static unsigned GetRegInfo2 (CodeSeg* S,
                             CodeEntry* E,
                             int Index,
                             Collection* Visited,
                             unsigned Used,
                             unsigned Unused,
                             unsigned Wanted)
/* Recursively called subfunction for GetRegInfo. */
{
    /* Follow the instruction flow recording register usage. */
    while (1) {

        unsigned R;

        /* Check if we have already visited the current code entry. If so,
        ** bail out.
        */
        if (CE_HasMark (E)) {
            break;
        }

        /* Mark this entry as already visited */
        CE_SetMark (E);
        CollAppend (Visited, E);

        /* Evaluate the used registers */
        R = E->Use;
        if (E->OPC == OP65_RTS ||
            ((E->Info & OF_UBRA) != 0 && E->JumpTo == 0)) {
            /* This instruction will leave the function */
            R |= S->ExitRegs;
        }
        if (R != REG_NONE) {
            /* We are not interested in the use of any register that has been
            ** used before.
            */
            R &= ~Unused;
            /* Remember the remaining registers */
            Used |= R;
        }

        /* Evaluate the changed registers */
        if ((R = E->Chg) != REG_NONE) {
            /* We are not interested in the use of any register that has been
            ** used before.
            */
            R &= ~Used;
            /* Remember the remaining registers */
            Unused |= R;
        }

        /* If we know about all registers now, bail out */
        if (((Used | Unused) & Wanted) == Wanted) {
            break;
        }

        /* If the instruction is an RTS or RTI, we're done */
        if ((E->Info & OF_RET) != 0) {
            break;
        }

        /* If we have an unconditional branch, follow this branch if possible,
        ** otherwise we're done.
        */
        if ((E->Info & OF_UBRA) != 0) {

            /* Does this jump have a valid target? */
            if (E->JumpTo) {

                /* Unconditional jump */
                E     = E->JumpTo->Owner;
                Index = -1;             /* Invalidate */

            } else {
                /* Jump outside means we're done */
                break;
            }

        /* In case of conditional branches, follow the branch if possible and
        ** follow the normal flow (branch not taken) afterwards. If we cannot
        ** follow the branch, we're done.
        */
        } else if ((E->Info & OF_CBRA) != 0) {

            /* Recursively determine register usage at the branch target */
            unsigned U1;
            unsigned U2;

            if (E->JumpTo) {

                /* Jump to internal label */
                U1 = GetRegInfo2 (S, E->JumpTo->Owner, -1, Visited, Used, Unused, Wanted);

            } else {

                /* Jump to external label. This will effectively exit the
                ** function, so we use the exitregs information here.
                */
                U1 = S->ExitRegs;

            }

            /* Get the next entry */
            if (Index < 0) {
                Index = CS_GetEntryIndex (S, E);
            }
            if ((E = CS_GetEntry (S, ++Index)) == 0) {
                Internal ("GetRegInfo2: No next entry!");
            }

            /* Follow flow if branch not taken */
            U2 = GetRegInfo2 (S, E, Index, Visited, Used, Unused, Wanted);

            /* Registers are used if they're use in any of the branches */
            return U1 | U2;

        } else {

            /* Just go to the next instruction */
            if (Index < 0) {
                Index = CS_GetEntryIndex (S, E);
            }
            E = CS_GetEntry (S, ++Index);
            if (E == 0) {
                /* No next entry */
                Internal ("GetRegInfo2: No next entry!");
            }

        }

    }

    /* Return to the caller the complement of all unused registers */
    return Used;
}
Пример #30
0
static void ReadO65RelocInfo (FILE* F, const O65Data* D, Collection* Reloc)
/* Read relocation data for one segment */
{
    /* Relocation starts at (start address - 1) */
    unsigned long Offs = (unsigned long) -1L;

    while (1) {

        O65Reloc* R;

        /* Read the next relocation offset */
        unsigned char C = Read8 (F);
        if (C == 0) {
            /* End of relocation table */
            break;
        }

        /* Create a new relocation entry */
        R = xmalloc (sizeof (*R));

        /* Handle overflow bytes */
        while (C == 0xFF) {
            Offs += 0xFE;
            C = Read8 (F);
        }

        /* Calculate the final offset */
        R->Offs = (Offs += C);

        /* Read typebyte and segment id */
        C = Read8 (F);
        R->Type   = (C & O65_RTYPE_MASK);
        R->SegID  = (C & O65_SEGID_MASK);

        /* Read an additional relocation value if there is one */
        R->SymIdx = (R->SegID == O65_SEGID_UNDEF)? ReadO65Size (F, &D->Header) : 0;
        switch (R->Type) {

            case O65_RTYPE_HIGH:
                if ((D->Header.mode & O65_RELOC_MASK) == O65_RELOC_BYTE) {
                    /* Low byte follows */
                    R->Val = Read8 (F);
                } else {
                    /* Low byte is zero */
                    R->Val = 0;
                }
                break;

            case O65_RTYPE_SEG:
                /* Low 16 byte of the segment address follow */
                R->Val = Read16 (F);
                break;

            default:
                R->Val = 0;
                break;
        }

        /* Insert this relocation entry into the collection */
        CollAppend (Reloc, R);
    }
}