1
0
mirror of https://github.com/cc65/cc65.git synced 2024-12-28 06:30:16 +00:00

Better register tracking in the optimizer

git-svn-id: svn://svn.cc65.org/cc65/trunk@812 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2001-07-24 17:07:33 +00:00
parent f249ae345e
commit 05eb03b32f
10 changed files with 773 additions and 340 deletions

View File

@ -161,7 +161,7 @@ static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D)
CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg,
CodeLabel* JumpTo, LineInfo* LI)
CodeLabel* JumpTo, LineInfo* LI)
/* Create a new code entry, initialize and return it */
{
/* Get the opcode description */
@ -179,6 +179,7 @@ CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg,
E->Size = GetInsnSize (E->OPC, E->AM);
E->JumpTo = JumpTo;
E->LI = UseLineInfo (LI);
E->RI = 0;
SetUseChgInfo (E, D);
InitCollection (&E->Labels);
@ -205,6 +206,9 @@ void FreeCodeEntry (CodeEntry* E)
/* Release the line info */
ReleaseLineInfo (E->LI);
/* Delete the register info */
CE_FreeRegInfo (E);
/* Free the entry */
xfree (E);
}
@ -273,6 +277,384 @@ void CE_SetArg (CodeEntry* E, const char* Arg)
int CE_KnownImm (const CodeEntry* E)
/* Return true if the argument of E is a known immediate value */
{
return (E->AM == AM65_IMM && (E->Flags & CEF_NUMARG) != 0);
}
void CE_FreeRegInfo (CodeEntry* E)
/* Free an existing register info struct */
{
if (E->RI) {
FreeRegInfo (E->RI);
E->RI = 0;
}
}
void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs)
/* Generate register info for this instruction. If an old info exists, it is
* overwritten.
*/
{
/* Pointers to the register contents */
RegContents* In;
RegContents* Out;
/* Function register usage */
unsigned char Use, Chg;
/* If we don't have a register info struct, allocate one. */
if (E->RI == 0) {
E->RI = NewRegInfo (InputRegs);
} else {
if (InputRegs) {
E->RI->In = *InputRegs;
} else {
RC_Invalidate (&E->RI->In);
}
E->RI->Out = E->RI->In;
}
/* Get pointers to the register contents */
In = &E->RI->In;
Out = &E->RI->Out;
/* Handle the different instructions */
switch (E->OPC) {
case OP65_ADC:
/* We don't know the value of the carry, so the result is
* always unknown.
*/
Out->RegA = -1;
break;
case OP65_AND:
if (In->RegA >= 0) {
if (CE_KnownImm (E)) {
Out->RegA = In->RegA & (short) E->Num;
} else {
Out->RegA = -1;
}
}
break;
case OP65_ASL:
if (E->AM == AM65_ACC && In->RegA >= 0) {
Out->RegA = (In->RegA << 1) & 0xFF;
}
break;
case OP65_BCC:
break;
case OP65_BCS:
break;
case OP65_BEQ:
break;
case OP65_BIT:
break;
case OP65_BMI:
break;
case OP65_BNE:
break;
case OP65_BPL:
break;
case OP65_BRA:
break;
case OP65_BRK:
break;
case OP65_BVC:
break;
case OP65_BVS:
break;
case OP65_CLC:
break;
case OP65_CLD:
break;
case OP65_CLI:
break;
case OP65_CLV:
break;
case OP65_CMP:
break;
case OP65_CPX:
break;
case OP65_CPY:
break;
case OP65_DEA:
if (In->RegA >= 0) {
Out->RegA = In->RegA - 1;
}
break;
case OP65_DEC:
if (E->AM == AM65_ACC && In->RegA >= 0) {
Out->RegA = In->RegA - 1;
}
break;
case OP65_DEX:
if (In->RegX >= 0) {
Out->RegX = In->RegX - 1;
}
break;
case OP65_DEY:
if (In->RegY >= 0) {
Out->RegY = In->RegY - 1;
}
break;
case OP65_EOR:
if (In->RegA >= 0) {
if (CE_KnownImm (E)) {
Out->RegA = In->RegA ^ (short) E->Num;
} else {
Out->RegA = -1;
}
}
break;
case OP65_INA:
if (In->RegA >= 0) {
Out->RegA = In->RegA + 1;
}
break;
case OP65_INC:
if (E->AM == AM65_ACC && In->RegA >= 0) {
Out->RegA = In->RegA + 1;
}
break;
case OP65_INX:
if (In->RegX >= 0) {
Out->RegX = In->RegX + 1;
}
break;
case OP65_INY:
if (In->RegY >= 0) {
Out->RegY = In->RegY + 1;
}
break;
case OP65_JCC:
break;
case OP65_JCS:
break;
case OP65_JEQ:
break;
case OP65_JMI:
break;
case OP65_JMP:
break;
case OP65_JNE:
break;
case OP65_JPL:
break;
case OP65_JSR:
/* Get the code info for the function */
GetFuncInfo (E->Arg, &Use, &Chg);
if (Chg & REG_A) {
Out->RegA = -1;
}
if (Chg & REG_X) {
Out->RegX = -1;
}
if (Chg & REG_Y) {
Out->RegY = -1;
}
break;
case OP65_JVC:
break;
case OP65_JVS:
break;
case OP65_LDA:
if (CE_KnownImm (E)) {
Out->RegA = (unsigned char) E->Num;
} else {
/* A is now unknown */
Out->RegA = -1;
}
break;
case OP65_LDX:
if (CE_KnownImm (E)) {
Out->RegX = (unsigned char) E->Num;
} else {
/* X is now unknown */
Out->RegX = -1;
}
break;
case OP65_LDY:
if (CE_KnownImm (E)) {
Out->RegY = (unsigned char) E->Num;
} else {
/* Y is now unknown */
Out->RegY = -1;
}
break;
case OP65_LSR:
if (E->AM == AM65_ACC && In->RegA >= 0) {
Out->RegA = (In->RegA >> 1) & 0xFF;
}
break;
case OP65_NOP:
break;
case OP65_ORA:
if (In->RegA >= 0) {
if (CE_KnownImm (E)) {
Out->RegA = In->RegA | (short) E->Num;
} else {
/* A is now unknown */
Out->RegA = -1;
}
}
break;
case OP65_PHA:
break;
case OP65_PHP:
break;
case OP65_PHX:
break;
case OP65_PHY:
break;
case OP65_PLA:
Out->RegA = -1;
break;
case OP65_PLP:
break;
case OP65_PLX:
Out->RegX = -1;
break;
case OP65_PLY:
Out->RegY = -1;
break;
case OP65_ROL:
Out->RegA = -1;
break;
case OP65_ROR:
Out->RegA = -1;
break;
case OP65_RTI:
break;
case OP65_RTS:
break;
case OP65_SBC:
/* We don't know the value of the carry bit */
Out->RegA = -1;
break;
case OP65_SEC:
break;
case OP65_SED:
break;
case OP65_SEI:
break;
case OP65_STA:
break;
case OP65_STX:
break;
case OP65_STY:
break;
case OP65_TAX:
Out->RegX = In->RegA;
break;
case OP65_TAY:
Out->RegY = In->RegA;
break;
case OP65_TRB:
/* For now... */
Out->RegA = -1;
break;
case OP65_TSB:
/* For now... */
Out->RegA = -1;
break;
case OP65_TSX:
Out->RegX = -1;
break;
case OP65_TXA:
Out->RegA = In->RegX;
break;
case OP65_TXS:
break;
case OP65_TYA:
Out->RegA = In->RegY;
break;
default:
break;
}
}
void CE_Output (const CodeEntry* E, FILE* F)
/* Output the code entry to a file */
{
@ -311,7 +693,7 @@ void CE_Output (const CodeEntry* E, FILE* F)
/* immidiate */
Chars += fprintf (F, "%*s#%s", 9-Chars, "", E->Arg);
break;
case AM_ABS:
case AM65_ZP:
case AM65_ABS:

View File

@ -48,6 +48,7 @@
#include "codelab.h"
#include "lineinfo.h"
#include "opcodes.h"
#include "reginfo.h"
@ -76,6 +77,7 @@ struct CodeEntry {
CodeLabel* JumpTo; /* Jump label */
Collection Labels; /* Labels for this instruction */
LineInfo* LI; /* Source line info for this insn */
RegInfo* RI; /* Register info for this insn */
};
@ -87,7 +89,7 @@ struct CodeEntry {
CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg,
CodeLabel* JumpTo, LineInfo* LI);
CodeLabel* JumpTo, LineInfo* LI);
/* Create a new code entry, initialize and return it */
void FreeCodeEntry (CodeEntry* E);
@ -170,6 +172,17 @@ INLINE void CE_ResetMark (CodeEntry* E)
void CE_SetArg (CodeEntry* E, const char* Arg);
/* Set a new argument for the given code entry. An old string is deleted. */
int CE_KnownImm (const CodeEntry* E);
/* Return true if the argument of E is a known immediate value */
void CE_FreeRegInfo (CodeEntry* E);
/* Free an existing register info struct */
void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs);
/* Generate register info for this instruction. If an old info exists, it is
* overwritten.
*/
void CE_Output (const CodeEntry* E, FILE* F);
/* Output the code entry to a file */
@ -180,4 +193,4 @@ void CE_Output (const CodeEntry* E, FILE* F);

View File

@ -85,6 +85,26 @@ CodeLabel* NewCodeLabel (const char* Name, unsigned Hash);
void FreeCodeLabel (CodeLabel* L);
/* Free the given code label */
#if defined(HAVE_INLINE)
INLINE unsigned CL_GetRefCount (const CodeLabel* L)
/* Get the number of references for this label */
{
return CollCount (&L->JumpFrom);
}
#else
# define CL_GetRefCount(L) CollCount (&(L)->JumpFrom)
#endif
#if defined(HAVE_INLINE)
INLINE struct CodeEntry* CL_GetRef (CodeLabel* L, unsigned Index)
/* Get a code entry referencing this label */
{
return CollAt (&L->JumpFrom, Index);
}
#else
# define CL_GetRef(L, Index) CollAt (&(L)->JumpFrom, (Index))
#endif
void CL_AddRef (CodeLabel* L, struct CodeEntry* E);
/* Let the CodeEntry E reference the label L */

View File

@ -63,7 +63,7 @@
static void CS_MoveLabelsToEntry (CodeSeg* S, CodeEntry* E)
/* Move all labels from the label pool to the given entry and remove them
/* Move all labels from the label pool to the given entry and remove them
* from the pool.
*/
{
@ -545,7 +545,7 @@ void CS_DelEntry (CodeSeg* S, unsigned Index)
FreeCodeEntry (E);
}
void CS_DelEntries (CodeSeg* S, unsigned Start, unsigned Count)
/* Delete a range of code entries. This includes removing references to labels,
@ -1000,4 +1000,104 @@ void CS_Output (const CodeSeg* S, FILE* F)
void CS_FreeRegInfo (CodeSeg* S)
/* Free register infos for all instructions */
{
unsigned I;
for (I = 0; I < CS_GetEntryCount (S); ++I) {
CE_FreeRegInfo (CS_GetEntry(S, I));
}
}
void CS_GenRegInfo (CodeSeg* S)
/* Generate register infos for all instructions */
{
unsigned I;
RegContents Regs;
RegContents* CurrentRegs;
int WasJump;
/* Be sure to delete all register infos */
CS_FreeRegInfo (S);
/* On entry, the register contents are unknown */
RC_Invalidate (&Regs);
CurrentRegs = &Regs;
/* First pass. Walk over all insns an note just the changes from one
* insn to the next one.
*/
WasJump = 0;
for (I = 0; I < CS_GetEntryCount (S); ++I) {
/* Get the next instruction */
CodeEntry* E = CollAtUnchecked (&S->Entries, I);
/* If the instruction has a label, we need some special handling */
unsigned LabelCount = CE_GetLabelCount (E);
if (LabelCount > 0) {
/* Loop over all entry points that jump here. If these entry
* points already have register info, check if all values are
* known and identical. If all values are identical, and the
* preceeding instruction was not an unconditional branch, check
* if the register value on exit of the preceeding instruction
* is also identical. If all these values are identical, the
* value of a register is known, otherwise it is unknown.
*/
CodeLabel* Label = CE_GetLabel (E, 0);
unsigned Entry;
if (WasJump) {
/* Preceeding insn was an unconditional branch */
CodeEntry* J = CL_GetRef(Label, 0);
if (J->RI) {
Regs = J->RI->Out;
} else {
RC_Invalidate (&Regs);
}
Entry = 1;
} else {
Regs = *CurrentRegs;
Entry = 0;
}
while (Entry < CL_GetRefCount (Label)) {
/* Get this entry */
CodeEntry* J = CL_GetRef (Label, Entry);
if (J->RI == 0) {
/* No register info for this entry, bail out */
RC_Invalidate (&Regs);
break;
}
if (J->RI->Out.RegA != Regs.RegA) {
Regs.RegA = -1;
}
if (J->RI->Out.RegX != Regs.RegX) {
Regs.RegX = -1;
}
if (J->RI->Out.RegY != Regs.RegY) {
Regs.RegY = -1;
}
++Entry;
}
/* Use this register info */
CurrentRegs = &Regs;
}
/* Generate register info for this instruction */
CE_GenRegInfo (E, CurrentRegs);
/* Output registers for this insn are input for the next */
CurrentRegs = &E->RI->Out;
/* Remember for the next insn if this insn was an uncondition branch */
WasJump = (E->Info & OF_UBRA) != 0;
}
}

View File

@ -215,6 +215,12 @@ INLINE unsigned CS_GetEntryCount (const CodeSeg* S)
# define CS_GetEntryCount(S) CollCount (&(S)->Entries)
#endif
void CS_FreeRegInfo (CodeSeg* S);
/* Free register infos for all instructions */
void CS_GenRegInfo (CodeSeg* S);
/* Generate register infos for all instructions */
/* End of codeseg.h */

View File

@ -56,20 +56,6 @@
/*****************************************************************************/
/* Helpers */
/*****************************************************************************/
static int IsKnownImm (const CodeEntry* E)
/* Return true if the argument of E is a known immediate value */
{
return (E->AM == AM65_IMM && (E->Flags & CEF_NUMARG) != 0);
}
/*****************************************************************************/
/* Replace jumps to RTS by RTS */
/*****************************************************************************/
@ -670,312 +656,56 @@ unsigned OptDuplicateLoads (CodeSeg* S)
/* Remove loads of registers where the value loaded is already in the register. */
{
unsigned Changes = 0;
unsigned I;
/* Remember the last load instructions for all registers */
int RegA = -1;
int RegX = -1;
int RegY = -1;
/* Generate register info for this step */
CS_GenRegInfo (S);
/* Walk over the entries */
unsigned I = 0;
I = 0;
while (I < CS_GetEntryCount (S)) {
unsigned char Use, Chg;
CodeEntry* N;
CodeEntry* N;
/* Get next entry */
CodeEntry* E = CS_GetEntry (S, I);
/* Assume we won't delete the entry */
int Delete = 0;
/* If this entry has a label attached, remove all knownledge about the
* register contents. This may be improved but for now it's ok.
*/
if (CE_HasLabel (E)) {
RegA = RegX = RegY = -1;
}
/* Assume we won't delete the entry */
int Delete = 0;
/* Handle the different instructions */
switch (E->OPC) {
case OP65_ADC:
/* We don't know the value of the carry, so the result is
* always unknown.
*/
RegA = -1;
break;
case OP65_AND:
if (RegA >= 0) {
if (IsKnownImm (E)) {
RegA &= (int) E->Num;
} else {
RegA = -1;
}
}
break;
case OP65_ASL:
if (RegA >= 0) {
RegA = (RegA << 1) & 0xFF;
}
break;
case OP65_BCC:
break;
case OP65_BCS:
break;
case OP65_BEQ:
break;
case OP65_BIT:
break;
case OP65_BMI:
break;
case OP65_BNE:
break;
case OP65_BPL:
break;
case OP65_BRA:
break;
case OP65_BRK:
break;
case OP65_BVC:
break;
case OP65_BVS:
break;
case OP65_CLC:
break;
case OP65_CLD:
break;
case OP65_CLI:
break;
case OP65_CLV:
break;
case OP65_CMP:
break;
case OP65_CPX:
break;
case OP65_CPY:
break;
case OP65_DEA:
DEC (RegA, 1);
break;
case OP65_DEC:
break;
case OP65_DEX:
DEC (RegX, 1);
break;
case OP65_DEY:
DEC (RegY, 1);
break;
case OP65_EOR:
if (RegA >= 0) {
if (IsKnownImm (E)) {
RegA ^= (int) E->Num;
} else {
RegA = -1;
}
}
break;
case OP65_INA:
INC (RegA, 1);
break;
case OP65_INC:
break;
case OP65_INX:
INC (RegX, 1);
break;
case OP65_INY:
INC (RegY, 1);
break;
case OP65_JCC:
break;
case OP65_JCS:
break;
case OP65_JEQ:
break;
case OP65_JMI:
break;
case OP65_JMP:
break;
case OP65_JNE:
break;
case OP65_JPL:
break;
case OP65_JSR:
/* Get the code info for the function */
GetFuncInfo (E->Arg, &Use, &Chg);
if (Chg & REG_A) {
RegA = -1;
}
if (Chg & REG_X) {
RegX = -1;
}
if (Chg & REG_Y) {
RegY = -1;
}
break;
case OP65_JVC:
break;
case OP65_JVS:
break;
case OP65_LDA:
if (IsKnownImm (E)) {
N = CS_GetNextEntry (S, I);
if (RegA >= 0 && RegA == E->Num && N && (N->Info & OF_FBRA) == 0) {
Delete = 1;
} else {
RegA = (unsigned char) E->Num;
}
} else {
/* A is now unknown */
RegA = -1;
if (E->RI->In.RegA >= 0 && /* Value of A is known */
CE_KnownImm (E) && /* Value to be loaded is known */
E->RI->In.RegA == E->Num && /* Both are equal */
(N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */
(N->Info & OF_FBRA) == 0) { /* Which is not a cond branch */
Delete = 1;
}
break;
case OP65_LDX:
if (IsKnownImm (E)) {
N = CS_GetNextEntry (S, I);
if (RegX >= 0 && RegX == E->Num && N && (N->Info & OF_FBRA) == 0) {
Delete = 1;
} else {
RegX = (unsigned char) E->Num;
}
} else {
/* X is now unknown */
RegX = -1;
if (E->RI->In.RegX >= 0 && /* Value of X is known */
CE_KnownImm (E) && /* Value to be loaded is known */
E->RI->In.RegX == E->Num && /* Both are equal */
(N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */
(N->Info & OF_FBRA) == 0) { /* Which is not a cond branch */
Delete = 1;
}
break;
case OP65_LDY:
if (IsKnownImm (E)) {
N = CS_GetNextEntry (S, I);
if (RegY >= 0 && RegY == E->Num && N && (N->Info & OF_FBRA) == 0) {
Delete = 1;
} else {
RegY = (unsigned char) E->Num;
}
} else {
/* Y is now unknown */
RegY = -1;
if (E->RI->In.RegY >= 0 && /* Value of Y is known */
CE_KnownImm (E) && /* Value to be loaded is known */
E->RI->In.RegY == E->Num && /* Both are equal */
(N = CS_GetNextEntry (S, I)) != 0 && /* There is a next entry */
(N->Info & OF_FBRA) == 0) { /* Which is not a cond branch */
Delete = 1;
}
break;
case OP65_LSR:
if (RegA >= 0) {
RegA = (RegA >> 1) & 0xFF;
}
break;
case OP65_NOP:
break;
case OP65_ORA:
if (RegA >= 0) {
if (IsKnownImm (E)) {
RegA |= (unsigned char) E->Num;
} else {
/* A is now unknown */
RegA = -1;
}
}
break;
case OP65_PHA:
break;
case OP65_PHP:
break;
case OP65_PHX:
break;
case OP65_PHY:
break;
case OP65_PLA:
RegA = -1;
break;
case OP65_PLP:
break;
case OP65_PLX:
RegX = -1;
break;
case OP65_PLY:
RegY = -1;
break;
case OP65_ROL:
RegA = -1;
break;
case OP65_ROR:
RegA = -1;
break;
case OP65_RTI:
break;
case OP65_RTS:
break;
case OP65_SBC:
RegA = -1;
break;
case OP65_SEC:
break;
case OP65_SED:
break;
case OP65_SEI:
break;
case OP65_STA:
break;
case OP65_STX:
/* If the value in the X register is known and the same as
* that in the A register, replace the store by a STA. The
@ -983,11 +713,13 @@ unsigned OptDuplicateLoads (CodeSeg* S)
* later. STX does support the zeropage,y addressing mode,
* so be sure to check for that.
*/
if (RegX >= 0 && RegX == RegA &&
E->AM != AM65_ABSY && E->AM != AM65_ZPY) {
if (E->RI->In.RegX >= 0 &&
E->RI->In.RegX == E->RI->In.RegA &&
E->AM != AM65_ABSY &&
E->AM != AM65_ZPY) {
/* Use the A register instead */
CE_ReplaceOPC (E, OP65_STA);
}
CE_ReplaceOPC (E, OP65_STA);
}
break;
case OP65_STY:
@ -998,65 +730,54 @@ unsigned OptDuplicateLoads (CodeSeg* S)
* replacement by X, but check for invalid addressing modes
* in this case.
*/
if (RegY >= 0) {
if (RegY == RegA) {
CE_ReplaceOPC (E, OP65_STA);
} else if (RegY == RegX && E->AM != AM65_ABSX && E->AM != AM65_ZPX) {
CE_ReplaceOPC (E, OP65_STX);
if (E->RI->In.RegY >= 0) {
if (E->RI->In.RegY == E->RI->In.RegA) {
CE_ReplaceOPC (E, OP65_STA);
} else if (E->RI->In.RegY == E->RI->In.RegX &&
E->AM != AM65_ABSX &&
E->AM != AM65_ZPX) {
CE_ReplaceOPC (E, OP65_STX);
}
}
break;
case OP65_TAX:
N = CS_GetNextEntry (S, I);
if (RegA >= 0 && RegA == RegX && N && (N->Info & OF_FBRA) == 0) {
if (E->RI->In.RegA >= 0 &&
E->RI->In.RegA == E->RI->In.RegX &&
(N = CS_GetNextEntry (S, I)) != 0 &&
(N->Info & OF_FBRA) == 0) {
/* Value is identical and not followed by a branch */
Delete = 1;
} else {
RegX = RegA;
}
break;
case OP65_TAY:
N = CS_GetNextEntry (S, I);
if (RegA >= 0 && RegA == RegY && N && (N->Info & OF_FBRA) == 0) {
if (E->RI->In.RegA >= 0 &&
E->RI->In.RegA == E->RI->In.RegY &&
(N = CS_GetNextEntry (S, I)) != 0 &&
(N->Info & OF_FBRA) == 0) {
/* Value is identical and not followed by a branch */
Delete = 1;
} else {
RegY = RegA;
}
break;
case OP65_TRB:
break;
case OP65_TSB:
break;
case OP65_TSX:
RegX = -1;
break;
case OP65_TXA:
N = CS_GetNextEntry (S, I);
if (RegX >= 0 && RegX == RegA && N && (N->Info & OF_FBRA) == 0) {
case OP65_TXA:
if (E->RI->In.RegX >= 0 &&
E->RI->In.RegX == E->RI->In.RegA &&
(N = CS_GetNextEntry (S, I)) != 0 &&
(N->Info & OF_FBRA) == 0) {
/* Value is identical and not followed by a branch */
Delete = 1;
} else {
RegA = RegX;
}
break;
case OP65_TXS:
break;
case OP65_TYA:
N = CS_GetNextEntry (S, I);
if (RegY >= 0 && RegY == RegA && N && (N->Info & OF_FBRA) == 0) {
if (E->RI->In.RegY >= 0 &&
E->RI->In.RegY == E->RI->In.RegA &&
(N = CS_GetNextEntry (S, I)) != 0 &&
(N->Info & OF_FBRA) == 0) {
/* Value is identical and not followed by a branch */
Delete = 1;
} else {
RegA = RegY;
}
break;

View File

@ -58,6 +58,7 @@ OBJS = anonname.o \
opcodes.o \
preproc.o \
pragma.o \
reginfo.o \
scanner.o \
segments.o \
stdfunc.o \

View File

@ -103,6 +103,7 @@ OBJS = anonname.obj \
opcodes.obj \
preproc.obj \
pragma.obj \
reginfo.obj \
scanner.obj \
segments.obj \
stdfunc.obj \
@ -170,6 +171,7 @@ FILE main.obj
FILE opcodes.obj
FILE preproc.obj
FILE pragma.obj
FILE reginfo.obj
FILE scanner.obj
FILE segments.obj
FILE stdfunc.obj

93
src/cc65/reginfo.c Normal file
View File

@ -0,0 +1,93 @@
/*****************************************************************************/
/* */
/* reginfo.c */
/* */
/* 6502 register tracking info */
/* */
/* */
/* */
/* (C) 2001 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
/* common */
#include "xmalloc.h"
/* cc65 */
#include "reginfo.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void RC_Invalidate (RegContents* C)
/* Invalidate all registers */
{
C->RegA = -1;
C->RegX = -1;
C->RegY = -1;
C->SRegLo = -1;
C->SRegHi = -1;
}
RegInfo* NewRegInfo (const RegContents* RC)
/* Allocate a new register info, initialize and return it. If RC is not
* a NULL pointer, it is used to initialize both, the input and output
* registers. If the pointer is NULL, all registers are set to unknown.
*/
{
/* Allocate memory */
RegInfo* RI = xmalloc (sizeof (RegInfo));
/* Initialize the registers */
if (RC) {
RI->In = *RC;
RI->Out = *RC;
} else {
RC_Invalidate (&RI->In);
RC_Invalidate (&RI->Out);
}
/* Return the new struct */
return RI;
}
void FreeRegInfo (RegInfo* RI)
/* Free a RegInfo struct */
{
xfree (RI);
}

95
src/cc65/reginfo.h Normal file
View File

@ -0,0 +1,95 @@
/*****************************************************************************/
/* */
/* reginfo.h */
/* */
/* 6502 register tracking info */
/* */
/* */
/* */
/* (C) 2001 Ullrich von Bassewitz */
/* Wacholderweg 14 */
/* D-70597 Stuttgart */
/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
/* warranty. In no event will the authors be held liable for any damages */
/* arising from the use of this software. */
/* */
/* Permission is granted to anyone to use this software for any purpose, */
/* including commercial applications, and to alter it and redistribute it */
/* freely, subject to the following restrictions: */
/* */
/* 1. The origin of this software must not be misrepresented; you must not */
/* claim that you wrote the original software. If you use this software */
/* in a product, an acknowledgment in the product documentation would be */
/* appreciated but is not required. */
/* 2. Altered source versions must be plainly marked as such, and must not */
/* be misrepresented as being the original software. */
/* 3. This notice may not be removed or altered from any source */
/* distribution. */
/* */
/*****************************************************************************/
#ifndef REGINFO_H
#define REGINFO_H
/* common */
#include "inline.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Register contents */
typedef struct RegContents RegContents;
struct RegContents {
short RegA;
short RegX;
short RegY;
short SRegLo;
short SRegHi;
};
/* Register change info */
typedef struct RegInfo RegInfo;
struct RegInfo {
RegContents In; /* Incoming register values */
RegContents Out; /* Outgoing register values */
};
/*****************************************************************************/
/* Code */
/*****************************************************************************/
void RC_Invalidate (RegContents* C);
/* Invalidate all registers */
RegInfo* NewRegInfo (const RegContents* RC);
/* Allocate a new register info, initialize and return it. If RC is not
* a NULL pointer, it is used to initialize both, the input and output
* registers. If the pointer is NULL, all registers are set to unknown.
*/
void FreeRegInfo (RegInfo* RI);
/* Free a RegInfo struct */
/* End of reginfo.h */
#endif