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 */
E->Size = GetInsnSize (E->OPC, E->AM);
E->JumpTo = JumpTo;
E->LI = UseLineInfo (LI);
+ E->RI = 0;
SetUseChgInfo (E, D);
InitCollection (&E->Labels);
/* Release the line info */
ReleaseLineInfo (E->LI);
+ /* Delete the register info */
+ CE_FreeRegInfo (E);
+
/* Free the entry */
xfree (E);
}
+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 */
{
/* immidiate */
Chars += fprintf (F, "%*s#%s", 9-Chars, "", E->Arg);
break;
-
+
case AM_ABS:
case AM65_ZP:
case AM65_ABS:
#include "codelab.h"
#include "lineinfo.h"
#include "opcodes.h"
+#include "reginfo.h"
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 */
};
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);
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 */
-
+
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 */
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.
*/
{
FreeCodeEntry (E);
}
-
+
void CS_DelEntries (CodeSeg* S, unsigned Start, unsigned Count)
/* Delete a range of code entries. This includes removing references to labels,
+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;
+ }
+}
+
+
# 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 */
-/*****************************************************************************/
-/* 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 */
/*****************************************************************************/
/* 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;
- }
- 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;
- }
+ 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_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
* 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:
* 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;
opcodes.o \
preproc.o \
pragma.o \
+ reginfo.o \
scanner.o \
segments.o \
stdfunc.o \
opcodes.obj \
preproc.obj \
pragma.obj \
+ reginfo.obj \
scanner.obj \
segments.obj \
stdfunc.obj \
FILE opcodes.obj
FILE preproc.obj
FILE pragma.obj
+FILE reginfo.obj
FILE scanner.obj
FILE segments.obj
FILE stdfunc.obj
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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);
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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
+
+
+