mirror of
https://github.com/cc65/cc65.git
synced 2025-01-11 11:30:13 +00:00
Fixed a problem with the Chg/Use flags
git-svn-id: svn://svn.cc65.org/cc65/trunk@734 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
a9702f8a52
commit
3c04d5777f
@ -133,6 +133,27 @@ static int NumArg (const char* Arg, unsigned long* Num)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D)
|
||||||
|
/* Set the Use and Chg in E */
|
||||||
|
{
|
||||||
|
/* If this is a subroutine call, or a jump to an external function,
|
||||||
|
* lookup the information about this function and use it. The jump itself
|
||||||
|
* does not change any registers, so we don't need to use the data from D.
|
||||||
|
*/
|
||||||
|
if (E->OPC == OPC_JSR || ((E->Info & OF_BRA) != 0 && E->JumpTo == 0)) {
|
||||||
|
/* A subroutine call or jump to external symbol (function exit) */
|
||||||
|
GetFuncInfo (E->Arg, &E->Use, &E->Chg);
|
||||||
|
} else {
|
||||||
|
/* Some other instruction. Use the values from the opcode description
|
||||||
|
* plus addressing mode info
|
||||||
|
*/
|
||||||
|
E->Use = D->Use | GetAMUseInfo (E->AM);
|
||||||
|
E->Chg = D->Chg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@ -145,7 +166,7 @@ CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg, CodeLabel* JumpTo)
|
|||||||
/* Get the opcode description */
|
/* Get the opcode description */
|
||||||
const OPCDesc* D = GetOPCDesc (OPC);
|
const OPCDesc* D = GetOPCDesc (OPC);
|
||||||
|
|
||||||
/* Allocate memory */
|
/* Allocate memory */
|
||||||
CodeEntry* E = xmalloc (sizeof (CodeEntry));
|
CodeEntry* E = xmalloc (sizeof (CodeEntry));
|
||||||
|
|
||||||
/* Initialize the fields */
|
/* Initialize the fields */
|
||||||
@ -155,24 +176,13 @@ CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg, CodeLabel* JumpTo)
|
|||||||
E->Hints = 0;
|
E->Hints = 0;
|
||||||
E->Arg = GetArgCopy (Arg);
|
E->Arg = GetArgCopy (Arg);
|
||||||
if (NumArg (E->Arg, &E->Num)) {
|
if (NumArg (E->Arg, &E->Num)) {
|
||||||
E-> Flags = CEF_NUMARG;
|
E-> Flags = CEF_NUMARG;
|
||||||
} else {
|
} else {
|
||||||
E->Flags = 0;
|
E->Flags = 0;
|
||||||
}
|
}
|
||||||
E->Info = D->Info;
|
E->Info = D->Info;
|
||||||
E->Use = D->Use;
|
|
||||||
E->Chg = D->Chg;
|
|
||||||
if (E->OPC == OPC_JSR) {
|
|
||||||
/* A subroutine call */
|
|
||||||
GetFuncInfo (E->Arg, &E->Use, &E->Chg);
|
|
||||||
} else if ((E->Info & OF_BRA) != 0 && JumpTo == 0) {
|
|
||||||
/* Jump to external symbol (function exit) */
|
|
||||||
GetFuncInfo (E->Arg, &E->Use, &E->Chg);
|
|
||||||
} else {
|
|
||||||
/* Some other instruction */
|
|
||||||
E->Use |= GetAMUseInfo (E->AM);
|
|
||||||
}
|
|
||||||
E->JumpTo = JumpTo;
|
E->JumpTo = JumpTo;
|
||||||
|
SetUseChgInfo (E, D);
|
||||||
InitCollection (&E->Labels);
|
InitCollection (&E->Labels);
|
||||||
|
|
||||||
/* If we have a label given, add this entry to the label */
|
/* If we have a label given, add this entry to the label */
|
||||||
@ -210,18 +220,10 @@ void ReplaceOPC (CodeEntry* E, opc_t OPC)
|
|||||||
const OPCDesc* D = GetOPCDesc (OPC);
|
const OPCDesc* D = GetOPCDesc (OPC);
|
||||||
|
|
||||||
/* Replace the opcode */
|
/* Replace the opcode */
|
||||||
E->OPC = OPC;
|
E->OPC = OPC;
|
||||||
E->Size = GetInsnSize (E->OPC, E->AM);
|
E->Size = GetInsnSize (E->OPC, E->AM);
|
||||||
E->Info = D->Info;
|
E->Info = D->Info;
|
||||||
E->Use = D->Use;
|
SetUseChgInfo (E, D);
|
||||||
E->Chg = D->Chg;
|
|
||||||
if (E->OPC == OPC_JSR) {
|
|
||||||
/* A subroutine call */
|
|
||||||
GetFuncInfo (E->Arg, &E->Use, &E->Chg);
|
|
||||||
} else {
|
|
||||||
/* Some other instruction */
|
|
||||||
E->Use |= GetAMUseInfo (E->AM);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -127,25 +127,24 @@ static int CompareFuncInfo (const void* Key, const void* Info)
|
|||||||
|
|
||||||
|
|
||||||
void GetFuncInfo (const char* Name, unsigned char* Use, unsigned char* Chg)
|
void GetFuncInfo (const char* Name, unsigned char* Use, unsigned char* Chg)
|
||||||
/* For the given function, lookup register information and combine it with
|
/* For the given function, lookup register information and store it into
|
||||||
* the information already in place. If the function is unknown, assume it
|
* the given variables. If the function is unknown, assume it will use and
|
||||||
* will use all registers and load all registers.
|
* load all registers.
|
||||||
* See codeinfo.h for possible flags.
|
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
/* Search for the function */
|
/* Search for the function */
|
||||||
const FuncInfo* Info = bsearch (Name, FuncInfoTable, FuncInfoCount,
|
const FuncInfo* Info = bsearch (Name, FuncInfoTable, FuncInfoCount,
|
||||||
sizeof(FuncInfo), CompareFuncInfo);
|
sizeof(FuncInfo), CompareFuncInfo);
|
||||||
|
|
||||||
/* Do we know the function? */
|
/* Do we know the function? */
|
||||||
if (Info) {
|
if (Info) {
|
||||||
/* Use the information we have */
|
/* Use the information we have */
|
||||||
*Use |= Info->Use;
|
*Use = Info->Use;
|
||||||
*Chg |= Info->Chg;
|
*Chg = Info->Chg;
|
||||||
} else {
|
} else {
|
||||||
/* Assume all registers used */
|
/* Assume all registers used */
|
||||||
*Use |= REG_AXY;
|
*Use = REG_AXY;
|
||||||
*Chg |= REG_AXY;
|
*Chg = REG_AXY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,9 +77,9 @@ struct CodeSeg;
|
|||||||
|
|
||||||
|
|
||||||
void GetFuncInfo (const char* Name, unsigned char* Use, unsigned char* Chg);
|
void GetFuncInfo (const char* Name, unsigned char* Use, unsigned char* Chg);
|
||||||
/* For the given function, lookup register information and combine it with
|
/* For the given function, lookup register information and store it into
|
||||||
* the information already in place. If the function is unknown, assume it
|
* the given variables. If the function is unknown, assume it will use and
|
||||||
* will use all registers and load all registers.
|
* load all registers.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
unsigned char GetRegInfo (struct CodeSeg* S, unsigned Index);
|
unsigned char GetRegInfo (struct CodeSeg* S, unsigned Index);
|
||||||
|
@ -217,38 +217,25 @@ unsigned OptJumpCascades (CodeSeg* S)
|
|||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
unsigned Changes = 0;
|
unsigned Changes = 0;
|
||||||
unsigned I;
|
|
||||||
|
|
||||||
/* Get the number of entries, bail out if we have no entries */
|
|
||||||
unsigned Count = GetCodeEntryCount (S);
|
|
||||||
if (Count == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Walk over all entries */
|
/* Walk over all entries */
|
||||||
I = 0;
|
unsigned I = 0;
|
||||||
while (I < Count) {
|
while (I < GetCodeEntryCount (S)) {
|
||||||
|
|
||||||
|
CodeEntry* N;
|
||||||
|
CodeLabel* OldLabel;
|
||||||
|
|
||||||
/* Get this entry */
|
/* Get this entry */
|
||||||
CodeEntry* E = GetCodeEntry (S, I);
|
CodeEntry* E = GetCodeEntry (S, I);
|
||||||
|
|
||||||
/* Check if it's a branch, if it has a jump label, and if this jump
|
/* Check if it's a branch, if it has a jump label, if this jump
|
||||||
* label is not attached to the instruction itself.
|
* label is not attached to the instruction itself, and if the
|
||||||
|
* target instruction is itself a branch.
|
||||||
*/
|
*/
|
||||||
if ((E->Info & OF_BRA) != 0 && E->JumpTo != 0 && E->JumpTo->Owner != E) {
|
if ((E->Info & OF_BRA) != 0 &&
|
||||||
|
(OldLabel = E->JumpTo) != 0 &&
|
||||||
/* Get the label this insn is branching to */
|
(N = OldLabel->Owner) != E &&
|
||||||
CodeLabel* OldLabel = E->JumpTo;
|
(N->Info & OF_BRA) != 0) {
|
||||||
|
|
||||||
/* Get the entry we're branching to */
|
|
||||||
CodeEntry* N = OldLabel->Owner;
|
|
||||||
|
|
||||||
/* If the entry we're branching to is not itself a branch, it is
|
|
||||||
* not what we're searching for.
|
|
||||||
*/
|
|
||||||
if ((N->Info & OF_BRA) == 0) {
|
|
||||||
goto NextEntry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check if we can use the final target label. This is the case,
|
/* Check if we can use the final target label. This is the case,
|
||||||
* if the target branch is an absolut branch, or if it is a
|
* if the target branch is an absolut branch, or if it is a
|
||||||
@ -259,23 +246,15 @@ unsigned OptJumpCascades (CodeSeg* S)
|
|||||||
GetBranchCond (E->OPC) == GetBranchCond (N->OPC))) {
|
GetBranchCond (E->OPC) == GetBranchCond (N->OPC))) {
|
||||||
|
|
||||||
/* This is a jump cascade and we may jump to the final target.
|
/* This is a jump cascade and we may jump to the final target.
|
||||||
* If we have a label, move the reference to this label. If
|
* Insert a new instruction, then remove the old one
|
||||||
* we don't have a label, use the argument instead.
|
|
||||||
*/
|
*/
|
||||||
if (N->JumpTo) {
|
CodeEntry* X = NewCodeEntry (E->OPC, E->AM, N->Arg, N->JumpTo);
|
||||||
/* Move the reference to the new insn */
|
|
||||||
MoveCodeLabelRef (S, E, N->JumpTo);
|
|
||||||
} else {
|
|
||||||
/* Remove the reference to the old label */
|
|
||||||
RemoveCodeLabelRef (S, E);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use the new argument */
|
/* Insert it behind E */
|
||||||
CodeEntrySetArg (E, N->Arg);
|
InsertCodeEntry (S, X, I+1);
|
||||||
|
|
||||||
/* Use the usage information from the new instruction */
|
/* Remove E */
|
||||||
E->Use = N->Use;
|
DelCodeEntry (S, I);
|
||||||
E->Chg = N->Chg;
|
|
||||||
|
|
||||||
/* Remember, we had changes */
|
/* Remember, we had changes */
|
||||||
++Changes;
|
++Changes;
|
||||||
@ -292,7 +271,6 @@ unsigned OptJumpCascades (CodeSeg* S)
|
|||||||
*/
|
*/
|
||||||
if ((E->Info & OF_CBRA) != 0 && (N->Info & OF_CBRA) != 0) {
|
if ((E->Info & OF_CBRA) != 0 && (N->Info & OF_CBRA) != 0) {
|
||||||
|
|
||||||
unsigned NI; /* Index of N */
|
|
||||||
CodeEntry* X; /* Instruction behind N */
|
CodeEntry* X; /* Instruction behind N */
|
||||||
CodeLabel* LX; /* Label attached to X */
|
CodeLabel* LX; /* Label attached to X */
|
||||||
|
|
||||||
@ -306,18 +284,14 @@ unsigned OptJumpCascades (CodeSeg* S)
|
|||||||
goto NextEntry;
|
goto NextEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We may jump behind this conditional branch. This means that
|
/* We may jump behind this conditional branch. Get the
|
||||||
* N may not be the last entry.
|
* pointer to the next instruction
|
||||||
*/
|
*/
|
||||||
NI = GetCodeEntryIndex (S, N);
|
if ((X = GetNextCodeEntry (S, GetCodeEntryIndex (S, N))) == 0) {
|
||||||
if (NI >= Count-1) {
|
/* N is the last entry, bail out */
|
||||||
/* N is last entry */
|
|
||||||
goto NextEntry;
|
goto NextEntry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the pointer to the next instruction */
|
|
||||||
X = GetCodeEntry (S, NI+1);
|
|
||||||
|
|
||||||
/* Get the label attached to X, create a new one if needed */
|
/* Get the label attached to X, create a new one if needed */
|
||||||
LX = GenCodeLabel (S, X);
|
LX = GenCodeLabel (S, X);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user