From 810e17edfefba76b3b3241e121b936572bf14a69 Mon Sep 17 00:00:00 2001 From: acqn Date: Tue, 8 Sep 2020 23:41:02 +0800 Subject: [PATCH] Fixed processor states tracking for the BIT/TRB/TSB opcode. Added new opcode descriptions about whether and how the opcode accesses memory. --- src/cc65/codeent.c | 34 ++++++++++++++++++++++++++---- src/cc65/opcodes.c | 52 +++++++++++++++++++++++----------------------- src/cc65/opcodes.h | 5 ++++- 3 files changed, 60 insertions(+), 31 deletions(-) diff --git a/src/cc65/codeent.c b/src/cc65/codeent.c index 085130001..d54be039a 100644 --- a/src/cc65/codeent.c +++ b/src/cc65/codeent.c @@ -889,12 +889,38 @@ void CE_GenRegInfo (CodeEntry* E, RegContents* InputRegs) Val = In->SRegHi; break; } + } else if (CE_IsConstImm (E)) { + /* 65C02 special */ + Val = (short) E->Num; } - Out->PFlags &= ~UNKNOWN_PFVAL_V; - if (Val & PFVAL_V) { - Out->PFlags |= PFVAL_V; + + /* BIT is unique with regards to the Z/V/N flags: + ** - The Z is set/cleared according to whether the AND result is zero. + ** - The V is coped directly from Bit 6 of the orginal argument. + ** - The N is coped directly from Bit 7 of the orginal argument. + ** Note the V/N flags are not affected in imm addressing mode supported by 65c02! + */ + if (E->AM == AM65_IMM) { + if (RegValIsKnown (Val)) { + Out->PFlags &= ~(UNKNOWN_PFVAL_V | UNKNOWN_PFVAL_N); + if (Val & PFVAL_V) { + Out->PFlags |= PFVAL_V; + } + Out->PFlags &= ~UNKNOWN_PFVAL_V; + if (Val & PFVAL_V) { + Out->PFlags |= PFVAL_V; + } + } else { + Out->PFlags |= UNKNOWN_PFVAL_V | UNKNOWN_PFVAL_N; + } } - DeduceZN (Out, Val); + if ((RegValIsKnown (Val) && RegValIsKnown (In->RegA))) { + Val &= In->RegA; + } else if (((RegValIsKnown (Val) && Val == 0) || + (RegValIsKnown (In->RegA) && In->RegA == 0))) { + Val = 0; + } + DeduceZ (Out, Val); break; case OP65_BMI: diff --git a/src/cc65/opcodes.c b/src/cc65/opcodes.c index 792b92f7c..4ec25f3bd 100644 --- a/src/cc65/opcodes.c +++ b/src/cc65/opcodes.c @@ -63,21 +63,21 @@ const OPCDesc OPCTable[OP65_COUNT] = { 0, /* size */ REG_A, /* use */ REG_A, /* chg */ - OF_SETF /* flags */ + OF_SETF | OF_READ /* flags */ }, { OP65_AND, /* opcode */ "and", /* mnemonic */ 0, /* size */ REG_A, /* use */ REG_A, /* chg */ - OF_SETF /* flags */ + OF_SETF | OF_READ /* flags */ }, { OP65_ASL, /* opcode */ "asl", /* mnemonic */ 0, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ - OF_SETF | OF_NOIMP /* flags */ + OF_SETF | OF_NOIMP | OF_RMW /* flags */ }, { OP65_BCC, /* opcode */ "bcc", /* mnemonic */ @@ -105,7 +105,7 @@ const OPCDesc OPCTable[OP65_COUNT] = { 0, /* size */ REG_A, /* use */ REG_NONE, /* chg */ - OF_SETF /* flags */ + OF_READ /* flags */ }, { OP65_BMI, /* opcode */ "bmi", /* mnemonic */ @@ -189,21 +189,21 @@ const OPCDesc OPCTable[OP65_COUNT] = { 0, /* size */ REG_A, /* use */ REG_NONE, /* chg */ - OF_SETF | OF_CMP /* flags */ + OF_SETF | OF_CMP | OF_READ /* flags */ }, { OP65_CPX, /* opcode */ "cpx", /* mnemonic */ 0, /* size */ REG_X, /* use */ REG_NONE, /* chg */ - OF_SETF | OF_CMP /* flags */ + OF_SETF | OF_CMP | OF_READ /* flags */ }, { OP65_CPY, /* opcode */ "cpy", /* mnemonic */ 0, /* size */ REG_Y, /* use */ REG_NONE, /* chg */ - OF_SETF | OF_CMP /* flags */ + OF_SETF | OF_CMP | OF_READ /* flags */ }, { OP65_DEA, /* opcode */ "dea", /* mnemonic */ @@ -217,7 +217,7 @@ const OPCDesc OPCTable[OP65_COUNT] = { 0, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ - OF_SETF | OF_NOIMP /* flags */ + OF_SETF | OF_NOIMP | OF_RMW /* flags */ }, { OP65_DEX, /* opcode */ "dex", /* mnemonic */ @@ -238,7 +238,7 @@ const OPCDesc OPCTable[OP65_COUNT] = { 0, /* size */ REG_A, /* use */ REG_A, /* chg */ - OF_SETF /* flags */ + OF_SETF | OF_READ /* flags */ }, { OP65_INA, /* opcode */ "ina", /* mnemonic */ @@ -252,7 +252,7 @@ const OPCDesc OPCTable[OP65_COUNT] = { 0, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ - OF_SETF | OF_NOIMP /* flags */ + OF_SETF | OF_NOIMP | OF_RMW /* flags */ }, { OP65_INX, /* opcode */ "inx", /* mnemonic */ @@ -301,7 +301,7 @@ const OPCDesc OPCTable[OP65_COUNT] = { 3, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ - OF_UBRA | OF_LBRA /* flags */ + OF_UBRA | OF_LBRA | OF_READ /* flags */ }, { OP65_JNE, /* opcode */ "jne", /* mnemonic */ @@ -322,7 +322,7 @@ const OPCDesc OPCTable[OP65_COUNT] = { 3, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ - OF_CALL /* flags */ + OF_CALL | OF_READ /* flags */ }, { OP65_JVC, /* opcode */ "jvc", /* mnemonic */ @@ -343,28 +343,28 @@ const OPCDesc OPCTable[OP65_COUNT] = { 0, /* size */ REG_NONE, /* use */ REG_A, /* chg */ - OF_LOAD | OF_SETF /* flags */ + OF_LOAD | OF_SETF | OF_READ /* flags */ }, { OP65_LDX, /* opcode */ "ldx", /* mnemonic */ 0, /* size */ REG_NONE, /* use */ REG_X, /* chg */ - OF_LOAD | OF_SETF /* flags */ + OF_LOAD | OF_SETF | OF_READ /* flags */ }, { OP65_LDY, /* opcode */ "ldy", /* mnemonic */ 0, /* size */ REG_NONE, /* use */ REG_Y, /* chg */ - OF_LOAD | OF_SETF /* flags */ + OF_LOAD | OF_SETF | OF_READ /* flags */ }, { OP65_LSR, /* opcode */ "lsr", /* mnemonic */ 0, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ - OF_SETF | OF_NOIMP /* flags */ + OF_SETF | OF_NOIMP | OF_RMW /* flags */ }, { OP65_NOP, /* opcode */ "nop", /* mnemonic */ @@ -378,7 +378,7 @@ const OPCDesc OPCTable[OP65_COUNT] = { 0, /* size */ REG_A, /* use */ REG_A, /* chg */ - OF_SETF /* flags */ + OF_SETF | OF_READ /* flags */ }, { OP65_PHA, /* opcode */ "pha", /* mnemonic */ @@ -441,14 +441,14 @@ const OPCDesc OPCTable[OP65_COUNT] = { 0, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ - OF_SETF | OF_NOIMP /* flags */ + OF_SETF | OF_NOIMP | OF_RMW /* flags */ }, { OP65_ROR, /* opcode */ "ror", /* mnemonic */ 0, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ - OF_SETF | OF_NOIMP /* flags */ + OF_SETF | OF_NOIMP | OF_RMW /* flags */ }, /* Mark RTI as "uses all registers but doesn't change them", so the ** optimizer won't remove preceeding loads. @@ -472,7 +472,7 @@ const OPCDesc OPCTable[OP65_COUNT] = { 0, /* size */ REG_A, /* use */ REG_A, /* chg */ - OF_SETF /* flags */ + OF_SETF | OF_READ /* flags */ }, { OP65_SEC, /* opcode */ "sec", /* mnemonic */ @@ -500,7 +500,7 @@ const OPCDesc OPCTable[OP65_COUNT] = { 0, /* size */ REG_A, /* use */ REG_NONE, /* chg */ - OF_STORE /* flags */ + OF_STORE | OF_WRITE /* flags */ }, { OP65_STP, /* opcode */ "stp", /* mnemonic */ @@ -514,21 +514,21 @@ const OPCDesc OPCTable[OP65_COUNT] = { 0, /* size */ REG_X, /* use */ REG_NONE, /* chg */ - OF_STORE /* flags */ + OF_STORE | OF_WRITE /* flags */ }, { OP65_STY, /* opcode */ "sty", /* mnemonic */ 0, /* size */ REG_Y, /* use */ REG_NONE, /* chg */ - OF_STORE /* flags */ + OF_STORE | OF_WRITE /* flags */ }, { OP65_STZ, /* opcode */ "stz", /* mnemonic */ 0, /* size */ REG_NONE, /* use */ REG_NONE, /* chg */ - OF_STORE /* flags */ + OF_STORE | OF_WRITE /* flags */ }, { OP65_TAX, /* opcode */ "tax", /* mnemonic */ @@ -549,14 +549,14 @@ const OPCDesc OPCTable[OP65_COUNT] = { 0, /* size */ REG_A, /* use */ REG_NONE, /* chg */ - OF_SETF /* flags */ + OF_RMW /* flags */ }, { OP65_TSB, /* opcode */ "tsb", /* mnemonic */ 0, /* size */ REG_A, /* use */ REG_NONE, /* chg */ - OF_SETF /* flags */ + OF_RMW /* flags */ }, { OP65_TSX, /* opcode */ "tsx", /* mnemonic */ diff --git a/src/cc65/opcodes.h b/src/cc65/opcodes.h index 24a289c26..162647eff 100644 --- a/src/cc65/opcodes.h +++ b/src/cc65/opcodes.h @@ -176,13 +176,16 @@ typedef enum { #define OF_XFR 0x0100U /* Transfer instruction */ #define OF_CALL 0x0200U /* A subroutine call */ #define OF_REG_INCDEC 0x0400U /* A register increment or decrement */ -#define OF_SETF 0x0800U /* Insn will set all load flags (not carry) */ +#define OF_SETF 0x0800U /* Insn will set both Z and N flags according to the result */ #define OF_CMP 0x1000U /* A compare A/X/Y instruction */ #define OF_NOIMP 0x2000U /* Implicit addressing mode is actually A */ +#define OF_READ 0x4000U /* Read from the memory address */ +#define OF_WRITE 0x8000U /* Write to the memory address */ /* Combined infos */ #define OF_BRA (OF_UBRA | OF_CBRA) /* Operation is a jump/branch */ #define OF_DEAD (OF_UBRA | OF_RET) /* Dead end - no exec behind this point */ +#define OF_RMW (OF_READ | OF_WRITE) /* Read, Modify and Write */ /* Opcode description */ typedef struct {