X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2Fcc65%2Fcodeent.c;h=3868a353103f7e0b14d80dac9f66ba7441019a1f;hb=3f4096d3030095605f28b4cfa73563c53a563df6;hp=e37d079f50a16df7edef3b5dc7400062069a075f;hpb=f4fbbc3dccb1353242a6ab69d6c5aa92e71f6673;p=cc65 diff --git a/src/cc65/codeent.c b/src/cc65/codeent.c index e37d079f5..3868a3531 100644 --- a/src/cc65/codeent.c +++ b/src/cc65/codeent.c @@ -6,10 +6,10 @@ /* */ /* */ /* */ -/* (C) 2001 Ullrich von Bassewitz */ -/* Wacholderweg 14 */ -/* D-70597 Stuttgart */ -/* EMail: uz@musoftware.de */ +/* (C) 2001-2003 Ullrich von Bassewitz */ +/* Römerstrasse 52 */ +/* D-70794 Filderstadt */ +/* EMail: uz@cc65.org */ /* */ /* */ /* This software is provided 'as-is', without any expressed or implied */ @@ -39,6 +39,7 @@ /* common */ #include "chartype.h" #include "check.h" +#include "debugflag.h" #include "xmalloc.h" #include "xsprintf.h" @@ -137,7 +138,7 @@ static int NumArg (const char* Arg, unsigned long* Num) static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D) /* Set the Use and Chg in E */ { - unsigned short Use; + const ZPInfo* Info; /* 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 @@ -156,26 +157,36 @@ static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D) /* Check for special zero page registers used */ switch (E->AM) { + case AM65_ACC: + if (E->OPC == OP65_ASL || E->OPC == OP65_DEC || + E->OPC == OP65_INC || E->OPC == OP65_LSR || + E->OPC == OP65_ROL || E->OPC == OP65_ROR) { + /* A is changed by these insns */ + E->Chg |= REG_A; + } + break; + case AM65_ZP: case AM65_ABS: /* Be conservative: */ case AM65_ZPX: case AM65_ABSX: case AM65_ABSY: - if (IsZPName (E->Arg, &Use) && Use != REG_NONE) { + Info = GetZPInfo (E->Arg); + if (Info && Info->ByteUse != REG_NONE) { if (E->OPC == OP65_ASL || E->OPC == OP65_DEC || - E->OPC == OP65_INC || E->OPC == OP65_LSR || - E->OPC == OP65_ROL || E->OPC == OP65_ROR || - E->OPC == OP65_TRB || E->OPC == OP65_TSB) { - /* The zp loc is both, input and output */ - E->Chg |= Use; - E->Use |= Use; + E->OPC == OP65_INC || E->OPC == OP65_LSR || + E->OPC == OP65_ROL || E->OPC == OP65_ROR || + E->OPC == OP65_TRB || E->OPC == OP65_TSB) { + /* The zp loc is both, input and output */ + E->Chg |= Info->ByteUse; + E->Use |= Info->ByteUse; } else if ((E->Info & OF_STORE) != 0) { - /* Just output */ - E->Chg |= Use; + /* Just output */ + E->Chg |= Info->ByteUse; } else { - /* Input only */ - E->Use |= Use; + /* Input only */ + E->Use |= Info->ByteUse; } } break; @@ -183,9 +194,10 @@ static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D) case AM65_ZPX_IND: case AM65_ZP_INDY: case AM65_ZP_IND: - if (IsZPName (E->Arg, &Use) && Use != REG_NONE) { + Info = GetZPInfo (E->Arg); + if (Info && Info->ByteUse != REG_NONE) { /* These addressing modes will never change the zp loc */ - E->Use |= Use; + E->Use |= Info->WordUse; } break; @@ -204,6 +216,21 @@ static void SetUseChgInfo (CodeEntry* E, const OPCDesc* D) +const char* MakeHexArg (unsigned Num) +/* Convert Num into a string in the form $XY, suitable for passing it as an + * argument to NewCodeEntry, and return a pointer to the string. + * BEWARE: The function returns a pointer to a static buffer, so the value is + * gone if you call it twice (and apart from that it's not thread and signal + * safe). + */ +{ + static char Buf[16]; + xsprintf (Buf, sizeof (Buf), "$%02X", (unsigned char) Num); + return Buf; +} + + + CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg, CodeLabel* JumpTo, LineInfo* LI) /* Create a new code entry, initialize and return it */ @@ -217,10 +244,10 @@ CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg, /* 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; + E->Flags = NumArg (E->Arg, &E->Num)? CEF_NUMARG : 0; /* Needs E->Arg */ E->Info = D->Info; - E->Size = GetInsnSize (E->OPC, E->AM); E->JumpTo = JumpTo; E->LI = UseLineInfo (LI); E->RI = 0; @@ -350,6 +377,45 @@ int CE_KnownImm (const CodeEntry* E) +int CE_UseLoadFlags (const CodeEntry* E) +/* Return true if the instruction uses any flags that are set by a load of + * a register (N and Z). + */ +{ + /* 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; +} + + + void CE_FreeRegInfo (CodeEntry* E) /* Free an existing register info struct */ { @@ -396,28 +462,64 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) /* We don't know the value of the carry, so the result is * always unknown. */ - Out->RegA = -1; + Out->RegA = UNKNOWN_REGVAL; break; case OP65_AND: - if (In->RegA >= 0) { + if (RegValIsKnown (In->RegA)) { if (CE_KnownImm (E)) { Out->RegA = In->RegA & (short) E->Num; + } else if (E->AM == AM65_ZP) { + switch (GetKnownReg (E->Use & REG_ZP, In)) { + case REG_TMP1: + Out->RegA = In->RegA & In->Tmp1; + break; + case REG_PTR1_LO: + Out->RegA = In->RegA & In->Ptr1Lo; + break; + case REG_PTR1_HI: + Out->RegA = In->RegA & In->Ptr1Hi; + break; + case REG_SREG_LO: + Out->RegA = In->RegA & In->SRegLo; + break; + case REG_SREG_HI: + Out->RegA = In->RegA & In->SRegHi; + break; + default: + Out->RegA = UNKNOWN_REGVAL; + break; + } } else { - Out->RegA = -1; + Out->RegA = UNKNOWN_REGVAL; } } break; case OP65_ASL: - if (E->AM == AM65_ACC && In->RegA >= 0) { + if (E->AM == AM65_ACC && RegValIsKnown (In->RegA)) { Out->RegA = (In->RegA << 1) & 0xFF; } else if (E->AM == AM65_ZP) { - if ((E->Chg & REG_SREG_LO) != 0 && In->SRegLo >= 0) { - Out->SRegLo = (In->SRegLo << 1) & 0xFF; - } else if ((E->Chg & REG_SREG_HI) != 0 && In->SRegHi >= 0) { - Out->SRegHi = (In->SRegHi << 1) & 0xFF; + switch (GetKnownReg (E->Chg & REG_ZP, In)) { + case REG_TMP1: + Out->Tmp1 = (In->Tmp1 << 1) & 0xFF; + break; + case REG_PTR1_LO: + Out->Ptr1Lo = (In->Ptr1Lo << 1) & 0xFF; + break; + case REG_PTR1_HI: + Out->Ptr1Hi = (In->Ptr1Hi << 1) & 0xFF; + break; + case REG_SREG_LO: + Out->SRegLo = (In->SRegLo << 1) & 0xFF; + break; + case REG_SREG_HI: + Out->SRegHi = (In->SRegHi << 1) & 0xFF; + break; } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); } break; @@ -476,71 +578,122 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) break; case OP65_DEA: - if (In->RegA >= 0) { + if (RegValIsKnown (In->RegA)) { Out->RegA = (In->RegA - 1) & 0xFF; } break; case OP65_DEC: - if (E->AM == AM65_ACC && In->RegA >= 0) { + if (E->AM == AM65_ACC && RegValIsKnown (In->RegA)) { Out->RegA = (In->RegA - 1) & 0xFF; } else if (E->AM == AM65_ZP) { - if ((E->Chg & REG_SREG_LO) != 0 && In->SRegLo >= 0) { - Out->SRegLo = (In->SRegLo - 1) & 0xFF; - } else if ((E->Chg & REG_SREG_HI) != 0 && In->SRegHi >= 0) { - Out->SRegHi = (In->SRegHi - 1) & 0xFF; + switch (GetKnownReg (E->Chg & REG_ZP, In)) { + case REG_TMP1: + Out->Tmp1 = (In->Tmp1 - 1) & 0xFF; + break; + case REG_PTR1_LO: + Out->Ptr1Lo = (In->Ptr1Lo - 1) & 0xFF; + break; + case REG_PTR1_HI: + Out->Ptr1Hi = (In->Ptr1Hi - 1) & 0xFF; + break; + case REG_SREG_LO: + Out->SRegLo = (In->SRegLo - 1) & 0xFF; + break; + case REG_SREG_HI: + Out->SRegHi = (In->SRegHi - 1) & 0xFF; + break; } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); } break; case OP65_DEX: - if (In->RegX >= 0) { + if (RegValIsKnown (In->RegX)) { Out->RegX = (In->RegX - 1) & 0xFF; } break; case OP65_DEY: - if (In->RegY >= 0) { + if (RegValIsKnown (In->RegY)) { Out->RegY = (In->RegY - 1) & 0xFF; } break; case OP65_EOR: - if (In->RegA >= 0) { + if (RegValIsKnown (In->RegA)) { if (CE_KnownImm (E)) { Out->RegA = In->RegA ^ (short) E->Num; + } else if (E->AM == AM65_ZP) { + switch (GetKnownReg (E->Use & REG_ZP, In)) { + case REG_TMP1: + Out->RegA = In->RegA ^ In->Tmp1; + break; + case REG_PTR1_LO: + Out->RegA = In->RegA ^ In->Ptr1Lo; + break; + case REG_PTR1_HI: + Out->RegA = In->RegA ^ In->Ptr1Hi; + break; + case REG_SREG_LO: + Out->RegA = In->RegA ^ In->SRegLo; + break; + case REG_SREG_HI: + Out->RegA = In->RegA ^ In->SRegHi; + break; + default: + Out->RegA = UNKNOWN_REGVAL; + break; + } } else { - Out->RegA = -1; + Out->RegA = UNKNOWN_REGVAL; } } break; case OP65_INA: - if (In->RegA >= 0) { + if (RegValIsKnown (In->RegA)) { Out->RegA = (In->RegA + 1) & 0xFF; } break; case OP65_INC: - if (E->AM == AM65_ACC && In->RegA >= 0) { - Out->RegA = (In->RegA + 1) & 0xFF; + if (E->AM == AM65_ACC && RegValIsKnown (In->RegA)) { + Out->RegA = (In->RegA + 1) & 0xFF; } else if (E->AM == AM65_ZP) { - if ((E->Chg & REG_SREG_LO) != 0 && In->SRegLo >= 0) { - Out->SRegLo = (In->SRegLo + 1) & 0xFF; - } else if ((E->Chg & REG_SREG_HI) != 0 && In->SRegHi >= 0) { - Out->SRegHi = (In->SRegHi + 1) & 0xFF; + switch (GetKnownReg (E->Chg & REG_ZP, In)) { + case REG_TMP1: + Out->Tmp1 = (In->Tmp1 + 1) & 0xFF; + break; + case REG_PTR1_LO: + Out->Ptr1Lo = (In->Ptr1Lo + 1) & 0xFF; + break; + case REG_PTR1_HI: + Out->Ptr1Hi = (In->Ptr1Hi + 1) & 0xFF; + break; + case REG_SREG_LO: + Out->SRegLo = (In->SRegLo + 1) & 0xFF; + break; + case REG_SREG_HI: + Out->SRegHi = (In->SRegHi + 1) & 0xFF; + break; } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); } break; case OP65_INX: - if (In->RegX >= 0) { + if (RegValIsKnown (In->RegX)) { Out->RegX = (In->RegX + 1) & 0xFF; } break; case OP65_INY: - if (In->RegY >= 0) { + if (RegValIsKnown (In->RegY)) { Out->RegY = (In->RegY + 1) & 0xFF; } break; @@ -570,20 +723,47 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) /* Get the code info for the function */ GetFuncInfo (E->Arg, &Use, &Chg); if (Chg & REG_A) { - Out->RegA = -1; + Out->RegA = UNKNOWN_REGVAL; } if (Chg & REG_X) { - Out->RegX = -1; + Out->RegX = UNKNOWN_REGVAL; } if (Chg & REG_Y) { - Out->RegY = -1; + Out->RegY = UNKNOWN_REGVAL; + } + if (Chg & REG_TMP1) { + Out->Tmp1 = UNKNOWN_REGVAL; + } + if (Chg & REG_PTR1_LO) { + Out->Ptr1Lo = UNKNOWN_REGVAL; + } + if (Chg & REG_PTR1_HI) { + Out->Ptr1Hi = UNKNOWN_REGVAL; } if (Chg & REG_SREG_LO) { - Out->SRegLo = -1; + Out->SRegLo = UNKNOWN_REGVAL; } if (Chg & REG_SREG_HI) { - Out->SRegHi = -1; + Out->SRegHi = UNKNOWN_REGVAL; } + /* ## FIXME: Quick hack for some known functions: */ + if (strcmp (E->Arg, "tosandax") == 0) { + if (In->RegA == 0) { + Out->RegA = 0; + } + if (In->RegX == 0) { + Out->RegX = 0; + } + } else if (strcmp (E->Arg, "tosorax") == 0) { + if (In->RegA == 0xFF) { + Out->RegA = 0xFF; + } + if (In->RegX == 0xFF) { + Out->RegX = 0xFF; + } + } else if (FindBoolCmpCond (E->Arg) != CMP_INV) { + Out->RegX = 0; + } break; case OP65_JVC: @@ -596,16 +776,29 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) if (CE_KnownImm (E)) { Out->RegA = (unsigned char) E->Num; } else if (E->AM == AM65_ZP) { - if (E->Use & REG_SREG_LO) { - Out->RegA = In->SRegLo; - } else if (E->Use & REG_SREG_HI) { - Out->RegA = In->SRegHi; - } else { - Out->RegA = -1; + switch (GetKnownReg (E->Use & REG_ZP, In)) { + case REG_TMP1: + Out->RegA = In->Tmp1; + break; + case REG_PTR1_LO: + Out->RegA = In->Ptr1Lo; + break; + case REG_PTR1_HI: + Out->RegA = In->Ptr1Hi; + break; + case REG_SREG_LO: + Out->RegA = In->SRegLo; + break; + case REG_SREG_HI: + Out->RegA = In->SRegHi; + break; + default: + Out->RegA = UNKNOWN_REGVAL; + break; } } else { /* A is now unknown */ - Out->RegA = -1; + Out->RegA = UNKNOWN_REGVAL; } break; @@ -613,16 +806,29 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) if (CE_KnownImm (E)) { Out->RegX = (unsigned char) E->Num; } else if (E->AM == AM65_ZP) { - if (E->Use & REG_SREG_LO) { - Out->RegX = In->SRegLo; - } else if (E->Use & REG_SREG_HI) { - Out->RegX = In->SRegHi; - } else { - Out->RegX = -1; + switch (GetKnownReg (E->Use & REG_ZP, In)) { + case REG_TMP1: + Out->RegX = In->Tmp1; + break; + case REG_PTR1_LO: + Out->RegX = In->Ptr1Lo; + break; + case REG_PTR1_HI: + Out->RegX = In->Ptr1Hi; + break; + case REG_SREG_LO: + Out->RegX = In->SRegLo; + break; + case REG_SREG_HI: + Out->RegX = In->SRegHi; + break; + default: + Out->RegX = UNKNOWN_REGVAL; + break; } } else { /* X is now unknown */ - Out->RegX = -1; + Out->RegX = UNKNOWN_REGVAL; } break; @@ -630,28 +836,56 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) if (CE_KnownImm (E)) { Out->RegY = (unsigned char) E->Num; } else if (E->AM == AM65_ZP) { - if (E->Use & REG_SREG_LO) { - Out->RegY = In->SRegLo; - } else if (E->Use & REG_SREG_HI) { - Out->RegY = In->SRegHi; - } else { - Out->RegY = -1; + switch (GetKnownReg (E->Use & REG_ZP, In)) { + case REG_TMP1: + Out->RegY = In->Tmp1; + break; + case REG_PTR1_LO: + Out->RegY = In->Ptr1Lo; + break; + case REG_PTR1_HI: + Out->RegY = In->Ptr1Hi; + break; + case REG_SREG_LO: + Out->RegY = In->SRegLo; + break; + case REG_SREG_HI: + Out->RegY = In->SRegHi; + break; + default: + Out->RegY = UNKNOWN_REGVAL; + break; } } else { /* Y is now unknown */ - Out->RegY = -1; + Out->RegY = UNKNOWN_REGVAL; } break; case OP65_LSR: - if (E->AM == AM65_ACC && In->RegA >= 0) { + if (E->AM == AM65_ACC && RegValIsKnown (In->RegA)) { Out->RegA = (In->RegA >> 1) & 0xFF; } else if (E->AM == AM65_ZP) { - if ((E->Chg & REG_SREG_LO) != 0 && In->SRegLo >= 0) { - Out->SRegLo = (In->SRegLo >> 1) & 0xFF; - } else if (E->Chg & REG_SREG_HI) { - Out->SRegHi = (In->SRegHi >> 1) & 0xFF; + switch (GetKnownReg (E->Chg & REG_ZP, In)) { + case REG_TMP1: + Out->Tmp1 = (In->Tmp1 >> 1) & 0xFF; + break; + case REG_PTR1_LO: + Out->Ptr1Lo = (In->Ptr1Lo >> 1) & 0xFF; + break; + case REG_PTR1_HI: + Out->Ptr1Hi = (In->Ptr1Hi >> 1) & 0xFF; + break; + case REG_SREG_LO: + Out->SRegLo = (In->SRegLo >> 1) & 0xFF; + break; + case REG_SREG_HI: + Out->SRegHi = (In->SRegHi >> 1) & 0xFF; + break; } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); } break; @@ -659,13 +893,34 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) 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; - } + if (RegValIsKnown (In->RegA)) { + if (CE_KnownImm (E)) { + Out->RegA = In->RegA | (short) E->Num; + } else if (E->AM == AM65_ZP) { + switch (GetKnownReg (E->Use & REG_ZP, In)) { + case REG_TMP1: + Out->RegA = In->RegA | In->Tmp1; + break; + case REG_PTR1_LO: + Out->RegA = In->RegA | In->Ptr1Lo; + break; + case REG_PTR1_HI: + Out->RegA = In->RegA | In->Ptr1Hi; + break; + case REG_SREG_LO: + Out->RegA = In->RegA | In->SRegLo; + break; + case REG_SREG_HI: + Out->RegA = In->RegA | In->SRegHi; + break; + default: + Out->RegA = UNKNOWN_REGVAL; + break; + } + } else { + /* A is now unknown */ + Out->RegA = UNKNOWN_REGVAL; + } } break; @@ -682,41 +937,73 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) break; case OP65_PLA: - Out->RegA = -1; + Out->RegA = UNKNOWN_REGVAL; break; case OP65_PLP: break; case OP65_PLX: - Out->RegX = -1; + Out->RegX = UNKNOWN_REGVAL; break; case OP65_PLY: - Out->RegY = -1; + Out->RegY = UNKNOWN_REGVAL; break; case OP65_ROL: + /* We don't know the value of the carry bit */ if (E->AM == AM65_ACC) { - Out->RegA = -1; + Out->RegA = UNKNOWN_REGVAL; } else if (E->AM == AM65_ZP) { - if (E->Chg & REG_SREG_LO) { - Out->SRegLo = -1; - } else if (E->Chg & REG_SREG_HI) { - Out->SRegHi = -1; - } + switch (GetKnownReg (E->Chg & REG_ZP, In)) { + case REG_TMP1: + Out->Tmp1 = UNKNOWN_REGVAL; + break; + case REG_PTR1_LO: + Out->Ptr1Lo = UNKNOWN_REGVAL; + break; + case REG_PTR1_HI: + Out->Ptr1Hi = UNKNOWN_REGVAL; + break; + case REG_SREG_LO: + Out->SRegLo = UNKNOWN_REGVAL; + break; + case REG_SREG_HI: + Out->SRegHi = UNKNOWN_REGVAL; + break; + } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); } break; case OP65_ROR: + /* We don't know the value of the carry bit */ if (E->AM == AM65_ACC) { - Out->RegA = -1; + Out->RegA = UNKNOWN_REGVAL; } else if (E->AM == AM65_ZP) { - if (E->Chg & REG_SREG_LO) { - Out->SRegLo = -1; - } else if (E->Chg & REG_SREG_HI) { - Out->SRegHi = -1; - } + switch (GetKnownReg (E->Chg & REG_ZP, In)) { + case REG_TMP1: + Out->Tmp1 = UNKNOWN_REGVAL; + break; + case REG_PTR1_LO: + Out->Ptr1Lo = UNKNOWN_REGVAL; + break; + case REG_PTR1_HI: + Out->Ptr1Hi = UNKNOWN_REGVAL; + break; + case REG_SREG_LO: + Out->SRegLo = UNKNOWN_REGVAL; + break; + case REG_SREG_HI: + Out->SRegHi = UNKNOWN_REGVAL; + break; + } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); } break; @@ -728,7 +1015,7 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) case OP65_SBC: /* We don't know the value of the carry bit */ - Out->RegA = -1; + Out->RegA = UNKNOWN_REGVAL; break; case OP65_SEC: @@ -742,54 +1029,204 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) case OP65_STA: if (E->AM == AM65_ZP) { - if (E->Chg & REG_SREG_LO) { - Out->SRegLo = In->RegA; - } else if (E->Chg & REG_SREG_HI) { - Out->SRegHi = In->RegA; + switch (GetKnownReg (E->Chg & REG_ZP, 0)) { + case REG_TMP1: + Out->Tmp1 = In->RegA; + break; + case REG_PTR1_LO: + Out->Ptr1Lo = In->RegA; + break; + case REG_PTR1_HI: + Out->Ptr1Hi = In->RegA; + break; + case REG_SREG_LO: + Out->SRegLo = In->RegA; + break; + case REG_SREG_HI: + Out->SRegHi = In->RegA; + break; } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); } break; case OP65_STX: if (E->AM == AM65_ZP) { - if (E->Chg & REG_SREG_LO) { - Out->SRegLo = In->RegX; - } else if (E->Chg & REG_SREG_HI) { - Out->SRegHi = In->RegX; + switch (GetKnownReg (E->Chg & REG_ZP, 0)) { + case REG_TMP1: + Out->Tmp1 = In->RegX; + break; + case REG_PTR1_LO: + Out->Ptr1Lo = In->RegX; + break; + case REG_PTR1_HI: + Out->Ptr1Hi = In->RegX; + break; + case REG_SREG_LO: + Out->SRegLo = In->RegX; + break; + case REG_SREG_HI: + Out->SRegHi = In->RegX; + break; } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); } break; case OP65_STY: if (E->AM == AM65_ZP) { - if (E->Chg & REG_SREG_LO) { - Out->SRegLo = In->RegY; - } else if (E->Chg & REG_SREG_HI) { - Out->SRegHi = In->RegY; + switch (GetKnownReg (E->Chg & REG_ZP, 0)) { + case REG_TMP1: + Out->Tmp1 = In->RegY; + break; + case REG_PTR1_LO: + Out->Ptr1Lo = In->RegY; + break; + case REG_PTR1_HI: + Out->Ptr1Hi = In->RegY; + break; + case REG_SREG_LO: + Out->SRegLo = In->RegY; + break; + case REG_SREG_HI: + Out->SRegHi = In->RegY; + break; } - } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); + } + break; + + case OP65_STZ: + if (E->AM == AM65_ZP) { + switch (GetKnownReg (E->Chg & REG_ZP, 0)) { + case REG_TMP1: + Out->Tmp1 = 0; + break; + case REG_PTR1_LO: + Out->Ptr1Lo = 0; + break; + case REG_PTR1_HI: + Out->Ptr1Hi = 0; + break; + case REG_SREG_LO: + Out->SRegLo = 0; + break; + case REG_SREG_HI: + Out->SRegHi = 0; + break; + } + } else if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); + } break; case OP65_TAX: Out->RegX = In->RegA; break; - case OP65_TAY: + case OP65_TAY: Out->RegY = In->RegA; break; case OP65_TRB: - /* For now... */ - Out->RegA = -1; + if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); + } else if (E->AM == AM65_ZP) { + if (RegValIsKnown (In->RegA)) { + switch (GetKnownReg (E->Chg & REG_ZP, In)) { + case REG_TMP1: + Out->Tmp1 &= ~In->RegA; + break; + case REG_PTR1_LO: + Out->Ptr1Lo &= ~In->RegA; + break; + case REG_PTR1_HI: + Out->Ptr1Hi &= ~In->RegA; + break; + case REG_SREG_LO: + Out->SRegLo &= ~In->RegA; + break; + case REG_SREG_HI: + Out->SRegHi &= ~In->RegA; + break; + } + } else { + switch (GetKnownReg (E->Chg & REG_ZP, In)) { + case REG_TMP1: + Out->Tmp1 = UNKNOWN_REGVAL; + break; + case REG_PTR1_LO: + Out->Ptr1Lo = UNKNOWN_REGVAL; + break; + case REG_PTR1_HI: + Out->Ptr1Hi = UNKNOWN_REGVAL; + break; + case REG_SREG_LO: + Out->SRegLo = UNKNOWN_REGVAL; + break; + case REG_SREG_HI: + Out->SRegHi = UNKNOWN_REGVAL; + break; + } + } + } break; case OP65_TSB: - /* For now... */ - Out->RegA = -1; + if (E->AM == AM65_ZPX) { + /* Invalidates all ZP registers */ + RC_InvalidateZP (Out); + } else if (E->AM == AM65_ZP) { + if (RegValIsKnown (In->RegA)) { + switch (GetKnownReg (E->Chg & REG_ZP, In)) { + case REG_TMP1: + Out->Tmp1 |= In->RegA; + break; + case REG_PTR1_LO: + Out->Ptr1Lo |= In->RegA; + break; + case REG_PTR1_HI: + Out->Ptr1Hi |= In->RegA; + break; + case REG_SREG_LO: + Out->SRegLo |= In->RegA; + break; + case REG_SREG_HI: + Out->SRegHi |= In->RegA; + break; + } + } else { + switch (GetKnownReg (E->Chg & REG_ZP, In)) { + case REG_TMP1: + Out->Tmp1 = UNKNOWN_REGVAL; + break; + case REG_PTR1_LO: + Out->Ptr1Lo = UNKNOWN_REGVAL; + break; + case REG_PTR1_HI: + Out->Ptr1Hi = UNKNOWN_REGVAL; + break; + case REG_SREG_LO: + Out->SRegLo = UNKNOWN_REGVAL; + break; + case REG_SREG_HI: + Out->SRegHi = UNKNOWN_REGVAL; + break; + } + } + } break; case OP65_TSX: - Out->RegX = -1; + Out->RegX = UNKNOWN_REGVAL; break; case OP65_TXA: @@ -821,17 +1258,11 @@ static char* RegInfoDesc (unsigned U, char* Buf) strcat (Buf, U & REG_A? "A" : "_"); strcat (Buf, U & REG_X? "X" : "_"); strcat (Buf, U & REG_Y? "Y" : "_"); - strcat (Buf, U & REG_SP? "S" : "_"); strcat (Buf, U & REG_TMP1? "T1" : "__"); - strcat (Buf, U & REG_TMP2? "T2" : "__"); - strcat (Buf, U & REG_TMP3? "T3" : "__"); - strcat (Buf, U & REG_TMP4? "T4" : "__"); strcat (Buf, U & REG_PTR1? "1" : "_"); strcat (Buf, U & REG_PTR2? "2" : "_"); - strcat (Buf, U & REG_PTR3? "3" : "_"); - strcat (Buf, U & REG_PTR4? "4" : "_"); strcat (Buf, U & REG_SAVE? "V" : "_"); - strcat (Buf, U & REG_BANK? "B" : "_"); + strcat (Buf, U & REG_SP? "S" : "_"); return Buf; } @@ -926,7 +1357,7 @@ void CE_Output (const CodeEntry* E, FILE* F) char Use [128]; char Chg [128]; fprintf (F, - "%*s; USE: %-20s CHG: %-20s SIZE: %u\n", + "%*s; USE: %-12s CHG: %-12s SIZE: %u\n", 30-Chars, "", RegInfoDesc (E->Use, Use), RegInfoDesc (E->Chg, Chg),