From 0b08eb0e6869a736e3015b161d715c02f6d21bfc Mon Sep 17 00:00:00 2001 From: cuz Date: Tue, 24 Jul 2001 20:13:10 +0000 Subject: [PATCH] More register tracking git-svn-id: svn://svn.cc65.org/cc65/trunk@815 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codeent.c | 2 +- src/cc65/codeinfo.c | 11 +++- src/cc65/codeseg.c | 154 ++++++++++++++++++++++++++++++++++++++++++-- src/cc65/codeseg.h | 5 ++ src/cc65/reginfo.c | 6 +- src/cc65/reginfo.h | 5 +- 6 files changed, 171 insertions(+), 12 deletions(-) diff --git a/src/cc65/codeent.c b/src/cc65/codeent.c index e6f9fe542..1594c8033 100644 --- a/src/cc65/codeent.c +++ b/src/cc65/codeent.c @@ -317,7 +317,7 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) } else { RC_Invalidate (&E->RI->In); } - E->RI->Out = E->RI->In; + E->RI->Out2 = E->RI->Out = E->RI->In; } /* Get pointers to the register contents */ diff --git a/src/cc65/codeinfo.c b/src/cc65/codeinfo.c index 7702a37ec..d3dee341d 100644 --- a/src/cc65/codeinfo.c +++ b/src/cc65/codeinfo.c @@ -130,8 +130,17 @@ static const FuncInfo FuncInfoTable[] = { { "shreax3", REG_AX, REG_AX }, { "staspidx", REG_A | REG_Y, REG_Y }, { "tosicmp", REG_AX, REG_AXY }, + { "tosdiva0", REG_AX, REG_AXY }, + { "tosdivax", REG_AX, REG_AXY }, + { "tosdiveax", REG_AX, REG_AXY }, + { "tosmula0", REG_AX, REG_AXY }, + { "tosmulax", REG_AX, REG_AXY }, + { "tosmuleax", REG_AX, REG_AXY }, { "tosshreax", REG_AX, REG_AXY }, -}; + { "tosumula0", REG_AX, REG_AXY }, + { "tosumulax", REG_AX, REG_AXY }, + { "tosumuleax", REG_AX, REG_AXY }, +}; #define FuncInfoCount (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0])) /* Table with names of zero page locations used by the compiler */ diff --git a/src/cc65/codeseg.c b/src/cc65/codeseg.c index 84c32797c..325eee20f 100644 --- a/src/cc65/codeseg.c +++ b/src/cc65/codeseg.c @@ -586,6 +586,22 @@ void CS_MoveEntries (CodeSeg* S, unsigned Start, unsigned Count, unsigned NewPos +struct CodeEntry* CS_GetPrevEntry (CodeSeg* S, unsigned Index) +/* Get the code entry preceeding the one with the index Index. If there is no + * preceeding code entry, return NULL. + */ +{ + if (Index == 0) { + /* This is the first entry */ + return 0; + } else { + /* Previous entry available */ + return CollAtUnchecked (&S->Entries, Index-1); + } +} + + + struct CodeEntry* CS_GetNextEntry (CodeSeg* S, unsigned Index) /* Get the code entry following the one with the index Index. If there is no * following code entry, return NULL. @@ -1032,6 +1048,8 @@ void CS_GenRegInfo (CodeSeg* S) WasJump = 0; for (I = 0; I < CS_GetEntryCount (S); ++I) { + CodeEntry* P; + /* Get the next instruction */ CodeEntry* E = CollAtUnchecked (&S->Entries, I); @@ -1053,7 +1071,7 @@ void CS_GenRegInfo (CodeSeg* S) /* Preceeding insn was an unconditional branch */ CodeEntry* J = CL_GetRef(Label, 0); if (J->RI) { - Regs = J->RI->Out; + Regs = J->RI->Out2; } else { RC_Invalidate (&Regs); } @@ -1071,13 +1089,13 @@ void CS_GenRegInfo (CodeSeg* S) RC_Invalidate (&Regs); break; } - if (J->RI->Out.RegA != Regs.RegA) { + if (J->RI->Out2.RegA != Regs.RegA) { Regs.RegA = -1; } - if (J->RI->Out.RegX != Regs.RegX) { + if (J->RI->Out2.RegX != Regs.RegX) { Regs.RegX = -1; } - if (J->RI->Out.RegY != Regs.RegY) { + if (J->RI->Out2.RegY != Regs.RegY) { Regs.RegY = -1; } ++Entry; @@ -1091,11 +1109,135 @@ void CS_GenRegInfo (CodeSeg* S) /* Generate register info for this instruction */ CE_GenRegInfo (E, CurrentRegs); + /* Remember for the next insn if this insn was an uncondition branch */ + WasJump = (E->Info & OF_UBRA) != 0; + /* 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; + /* If this insn is a branch on zero flag, we may have more info on + * register contents for one of both flow directions, but only if + * there is a previous instruction. + */ + if ((E->Info & OF_ZBRA) != 0 && (P = CS_GetPrevEntry (S, I)) != 0) { + + /* Get the branch condition */ + bc_t BC = GetBranchCond (E->OPC); + + /* Check the previous instruction */ + switch (P->OPC) { + + case OP65_ADC: + case OP65_AND: + case OP65_DEA: + case OP65_EOR: + case OP65_INA: + case OP65_LDA: + case OP65_ORA: + case OP65_PLA: + case OP65_SBC: + /* A is zero in one execution flow direction */ + if (BC == BC_EQ) { + E->RI->Out2.RegA = 0; + } else { + E->RI->Out.RegA = 0; + } + break; + + case OP65_CMP: + /* If this is an immidiate compare, the A register has + * the value of the compare later. + */ + if (CE_KnownImm (P)) { + if (BC == BC_EQ) { + E->RI->Out2.RegA = (unsigned char)P->Num; + } else { + E->RI->Out.RegA = (unsigned char)P->Num; + } + } + break; + + case OP65_CPX: + /* If this is an immidiate compare, the X register has + * the value of the compare later. + */ + if (CE_KnownImm (P)) { + if (BC == BC_EQ) { + E->RI->Out2.RegX = (unsigned char)P->Num; + } else { + E->RI->Out.RegX = (unsigned char)P->Num; + } + } + break; + + case OP65_CPY: + /* If this is an immidiate compare, the Y register has + * the value of the compare later. + */ + if (CE_KnownImm (P)) { + if (BC == BC_EQ) { + E->RI->Out2.RegY = (unsigned char)P->Num; + } else { + E->RI->Out.RegY = (unsigned char)P->Num; + } + } + break; + + case OP65_DEX: + case OP65_INX: + case OP65_LDX: + case OP65_PLX: + /* X is zero in one execution flow direction */ + if (BC == BC_EQ) { + E->RI->Out2.RegX = 0; + } else { + E->RI->Out.RegX = 0; + } + break; + + case OP65_DEY: + case OP65_INY: + case OP65_LDY: + case OP65_PLY: + /* X is zero in one execution flow direction */ + if (BC == BC_EQ) { + E->RI->Out2.RegY = 0; + } else { + E->RI->Out.RegY = 0; + } + break; + + case OP65_TAX: + case OP65_TXA: + /* If the branch is a beq, both A and X are zero at the + * branch target, otherwise they are zero at the next + * insn. + */ + if (BC == BC_EQ) { + E->RI->Out2.RegA = E->RI->Out2.RegX = 0; + } else { + E->RI->Out.RegA = E->RI->Out.RegX = 0; + } + break; + + case OP65_TAY: + case OP65_TYA: + /* If the branch is a beq, both A and Y are zero at the + * branch target, otherwise they are zero at the next + * insn. + */ + if (BC == BC_EQ) { + E->RI->Out2.RegA = E->RI->Out2.RegY = 0; + } else { + E->RI->Out.RegA = E->RI->Out.RegY = 0; + } + break; + + default: + break; + + } + } } } diff --git a/src/cc65/codeseg.h b/src/cc65/codeseg.h index 99342f423..f09c0d117 100644 --- a/src/cc65/codeseg.h +++ b/src/cc65/codeseg.h @@ -149,6 +149,11 @@ INLINE struct CodeEntry* CS_GetEntry (CodeSeg* S, unsigned Index) # define CS_GetEntry(S, Index) CollAt(&(S)->Entries, (Index)) #endif +struct CodeEntry* CS_GetPrevEntry (CodeSeg* S, unsigned Index); +/* Get the code entry preceeding the one with the index Index. If there is no + * preceeding code entry, return NULL. + */ + struct CodeEntry* CS_GetNextEntry (CodeSeg* S, unsigned Index); /* Get the code entry following the one with the index Index. If there is no * following code entry, return NULL. diff --git a/src/cc65/reginfo.c b/src/cc65/reginfo.c index f62dd3791..c8a6d094b 100644 --- a/src/cc65/reginfo.c +++ b/src/cc65/reginfo.c @@ -70,11 +70,13 @@ RegInfo* NewRegInfo (const RegContents* RC) /* Initialize the registers */ if (RC) { - RI->In = *RC; - RI->Out = *RC; + RI->In = *RC; + RI->Out = *RC; + RI->Out2 = *RC; } else { RC_Invalidate (&RI->In); RC_Invalidate (&RI->Out); + RC_Invalidate (&RI->Out2); } /* Return the new struct */ diff --git a/src/cc65/reginfo.h b/src/cc65/reginfo.h index 21415a819..bcf760b16 100644 --- a/src/cc65/reginfo.h +++ b/src/cc65/reginfo.h @@ -62,8 +62,9 @@ struct RegContents { /* Register change info */ typedef struct RegInfo RegInfo; struct RegInfo { - RegContents In; /* Incoming register values */ - RegContents Out; /* Outgoing register values */ + RegContents In; /* Incoming register values */ + RegContents Out; /* Outgoing register values */ + RegContents Out2; /* Alternative outgoing reg values for branches */ }; -- 2.39.2