Added processor flags usage tracking.

Added ZNRegs for tracking what register(s) Z/N flags currently reflect.
Added utility functions to check if the specified processor state is known to be a certain value.
This commit is contained in:
acqn 2020-09-08 23:40:58 +08:00 committed by Oliver Schmidt
parent fe3f267233
commit 66c5faeb9a
9 changed files with 1371 additions and 656 deletions

File diff suppressed because it is too large Load Diff

View File

@ -73,8 +73,8 @@ struct CodeEntry {
char* Arg; /* Argument as string */
unsigned long Num; /* Numeric argument */
unsigned short Info; /* Additional code info */
unsigned short Use; /* Registers used */
unsigned short Chg; /* Registers changed/destroyed */
unsigned int Use; /* Registers used */
unsigned int Chg; /* Registers changed/destroyed */
CodeLabel* JumpTo; /* Jump label */
Collection Labels; /* Labels for this instruction */
LineInfo* LI; /* Source line info for this insn */

View File

@ -77,8 +77,8 @@ static const char BoolTransformerTab [][8] = {
typedef struct FuncInfo FuncInfo;
struct FuncInfo {
const char* Name; /* Function name */
unsigned short Use; /* Register usage */
unsigned short Chg; /* Changed/destroyed registers */
unsigned Use; /* Register usage */
unsigned Chg; /* Changed/destroyed registers */
};
/* Note for the shift functions: Shifts are done modulo 32, so all shift
@ -86,264 +86,264 @@ struct FuncInfo {
** anyway.
*/
static const FuncInfo FuncInfoTable[] = {
{ "addeq0sp", REG_AX, REG_AXY },
{ "addeqysp", REG_AXY, REG_AXY },
{ "addysp", REG_Y, REG_NONE },
{ "aslax1", REG_AX, REG_AX | REG_TMP1 },
{ "aslax2", REG_AX, REG_AX | REG_TMP1 },
{ "aslax3", REG_AX, REG_AX | REG_TMP1 },
{ "aslax4", REG_AX, REG_AX | REG_TMP1 },
{ "aslaxy", REG_AXY, REG_AXY | REG_TMP1 },
{ "asleax1", REG_EAX, REG_EAX | REG_TMP1 },
{ "asleax2", REG_EAX, REG_EAX | REG_TMP1 },
{ "asleax3", REG_EAX, REG_EAX | REG_TMP1 },
{ "asleax4", REG_EAX, REG_EAXY | REG_TMP1 },
{ "asrax1", REG_AX, REG_AX | REG_TMP1 },
{ "asrax2", REG_AX, REG_AX | REG_TMP1 },
{ "asrax3", REG_AX, REG_AX | REG_TMP1 },
{ "asrax4", REG_AX, REG_AX | REG_TMP1 },
{ "asraxy", REG_AXY, REG_AXY | REG_TMP1 },
{ "asreax1", REG_EAX, REG_EAX | REG_TMP1 },
{ "asreax2", REG_EAX, REG_EAX | REG_TMP1 },
{ "asreax3", REG_EAX, REG_EAX | REG_TMP1 },
{ "asreax4", REG_EAX, REG_EAXY | REG_TMP1 },
{ "bcasta", REG_A, REG_AX },
{ "bcastax", REG_AX, REG_AX },
{ "bcasteax", REG_EAX, REG_EAX | REG_TMP1 },
{ "bnega", REG_A, REG_AX },
{ "bnegax", REG_AX, REG_AX },
{ "bnegeax", REG_EAX, REG_EAX | REG_TMP1 },
{ "booleq", REG_NONE, REG_AX },
{ "boolge", REG_NONE, REG_AX },
{ "boolgt", REG_NONE, REG_AX },
{ "boolle", REG_NONE, REG_AX },
{ "boollt", REG_NONE, REG_AX },
{ "boolne", REG_NONE, REG_AX },
{ "booluge", REG_NONE, REG_AX },
{ "boolugt", REG_NONE, REG_AX },
{ "boolule", REG_NONE, REG_AX },
{ "boolult", REG_NONE, REG_AX },
{ "callax", REG_AX, REG_ALL },
{ "complax", REG_AX, REG_AX },
{ "decax1", REG_AX, REG_AX },
{ "decax2", REG_AX, REG_AX },
{ "decax3", REG_AX, REG_AX },
{ "decax4", REG_AX, REG_AX },
{ "decax5", REG_AX, REG_AX },
{ "decax6", REG_AX, REG_AX },
{ "decax7", REG_AX, REG_AX },
{ "decax8", REG_AX, REG_AX },
{ "decaxy", REG_AXY, REG_AX | REG_TMP1 },
{ "deceaxy", REG_EAXY, REG_EAX },
{ "decsp1", REG_NONE, REG_Y },
{ "decsp2", REG_NONE, REG_A },
{ "decsp3", REG_NONE, REG_A },
{ "decsp4", REG_NONE, REG_A },
{ "decsp5", REG_NONE, REG_A },
{ "decsp6", REG_NONE, REG_A },
{ "decsp7", REG_NONE, REG_A },
{ "decsp8", REG_NONE, REG_A },
{ "incax1", REG_AX, REG_AX },
{ "incax2", REG_AX, REG_AX },
{ "incax3", REG_AX, REG_AXY | REG_TMP1 },
{ "incax4", REG_AX, REG_AXY | REG_TMP1 },
{ "incax5", REG_AX, REG_AXY | REG_TMP1 },
{ "incax6", REG_AX, REG_AXY | REG_TMP1 },
{ "incax7", REG_AX, REG_AXY | REG_TMP1 },
{ "incax8", REG_AX, REG_AXY | REG_TMP1 },
{ "incaxy", REG_AXY, REG_AXY | REG_TMP1 },
{ "incsp1", REG_NONE, REG_NONE },
{ "incsp2", REG_NONE, REG_Y },
{ "incsp3", REG_NONE, REG_Y },
{ "incsp4", REG_NONE, REG_Y },
{ "incsp5", REG_NONE, REG_Y },
{ "incsp6", REG_NONE, REG_Y },
{ "incsp7", REG_NONE, REG_Y },
{ "incsp8", REG_NONE, REG_Y },
{ "laddeq", REG_EAXY|REG_PTR1_LO, REG_EAXY | REG_PTR1_HI },
{ "laddeq0sp", REG_EAX, REG_EAXY },
{ "laddeq1", REG_Y | REG_PTR1_LO, REG_EAXY | REG_PTR1_HI },
{ "laddeqa", REG_AY | REG_PTR1_LO, REG_EAXY | REG_PTR1_HI },
{ "laddeqysp", REG_EAXY, REG_EAXY },
{ "ldaidx", REG_AXY, REG_AX | REG_PTR1 },
{ "ldauidx", REG_AXY, REG_AX | REG_PTR1 },
{ "ldax0sp", REG_NONE, REG_AXY },
{ "ldaxi", REG_AX, REG_AXY | REG_PTR1 },
{ "ldaxidx", REG_AXY, REG_AXY | REG_PTR1 },
{ "ldaxysp", REG_Y, REG_AXY },
{ "ldeax0sp", REG_NONE, REG_EAXY },
{ "ldeaxi", REG_AX, REG_EAXY | REG_PTR1 },
{ "ldeaxidx", REG_AXY, REG_EAXY | REG_PTR1 },
{ "ldeaxysp", REG_Y, REG_EAXY },
{ "leaa0sp", REG_A, REG_AX },
{ "leaaxsp", REG_AX, REG_AX },
{ "lsubeq", REG_EAXY|REG_PTR1_LO, REG_EAXY | REG_PTR1_HI },
{ "lsubeq0sp", REG_EAX, REG_EAXY },
{ "lsubeq1", REG_Y | REG_PTR1_LO, REG_EAXY | REG_PTR1_HI },
{ "lsubeqa", REG_AY | REG_PTR1_LO, REG_EAXY | REG_PTR1_HI },
{ "lsubeqysp", REG_EAXY, REG_EAXY },
{ "mulax10", REG_AX, REG_AX | REG_PTR1 },
{ "mulax3", REG_AX, REG_AX | REG_PTR1 },
{ "mulax5", REG_AX, REG_AX | REG_PTR1 },
{ "mulax6", REG_AX, REG_AX | REG_PTR1 },
{ "mulax7", REG_AX, REG_AX | REG_PTR1 },
{ "mulax9", REG_AX, REG_AX | REG_PTR1 },
{ "negax", REG_AX, REG_AX },
{ "push0", REG_NONE, REG_AXY },
{ "push0ax", REG_AX, REG_Y | REG_SREG },
{ "push1", REG_NONE, REG_AXY },
{ "push2", REG_NONE, REG_AXY },
{ "push3", REG_NONE, REG_AXY },
{ "push4", REG_NONE, REG_AXY },
{ "push5", REG_NONE, REG_AXY },
{ "push6", REG_NONE, REG_AXY },
{ "push7", REG_NONE, REG_AXY },
{ "pusha", REG_A, REG_Y },
{ "pusha0", REG_A, REG_XY },
{ "pusha0sp", REG_NONE, REG_AY },
{ "pushaFF", REG_A, REG_Y },
{ "pushax", REG_AX, REG_Y },
{ "pushaysp", REG_Y, REG_AY },
{ "pushc0", REG_NONE, REG_A | REG_Y },
{ "pushc1", REG_NONE, REG_A | REG_Y },
{ "pushc2", REG_NONE, REG_A | REG_Y },
{ "pusheax", REG_EAX, REG_Y },
{ "pushl0", REG_NONE, REG_AXY },
{ "pushw", REG_AX, REG_AXY | REG_PTR1 },
{ "pushw0sp", REG_NONE, REG_AXY },
{ "pushwidx", REG_AXY, REG_AXY | REG_PTR1 },
{ "pushwysp", REG_Y, REG_AXY },
{ "regswap", REG_AXY, REG_AXY | REG_TMP1 },
{ "regswap1", REG_XY, REG_A },
{ "regswap2", REG_XY, REG_A | REG_Y },
{ "return0", REG_NONE, REG_AX },
{ "return1", REG_NONE, REG_AX },
{ "shlax1", REG_AX, REG_AX | REG_TMP1 },
{ "shlax2", REG_AX, REG_AX | REG_TMP1 },
{ "shlax3", REG_AX, REG_AX | REG_TMP1 },
{ "shlax4", REG_AX, REG_AX | REG_TMP1 },
{ "shlaxy", REG_AXY, REG_AXY | REG_TMP1 },
{ "shleax1", REG_EAX, REG_EAX | REG_TMP1 },
{ "shleax2", REG_EAX, REG_EAX | REG_TMP1 },
{ "shleax3", REG_EAX, REG_EAX | REG_TMP1 },
{ "shleax4", REG_EAX, REG_EAXY | REG_TMP1 },
{ "shrax1", REG_AX, REG_AX | REG_TMP1 },
{ "shrax2", REG_AX, REG_AX | REG_TMP1 },
{ "shrax3", REG_AX, REG_AX | REG_TMP1 },
{ "shrax4", REG_AX, REG_AX | REG_TMP1 },
{ "shraxy", REG_AXY, REG_AXY | REG_TMP1 },
{ "shreax1", REG_EAX, REG_EAX | REG_TMP1 },
{ "shreax2", REG_EAX, REG_EAX | REG_TMP1 },
{ "shreax3", REG_EAX, REG_EAX | REG_TMP1 },
{ "shreax4", REG_EAX, REG_EAXY | REG_TMP1 },
{ "staspidx", REG_A | REG_Y, REG_Y | REG_TMP1 | REG_PTR1 },
{ "stax0sp", REG_AX, REG_Y },
{ "staxspidx", REG_AXY, REG_TMP1 | REG_PTR1 },
{ "staxysp", REG_AXY, REG_Y },
{ "steax0sp", REG_EAX, REG_Y },
{ "steaxysp", REG_EAXY, REG_Y },
{ "subeq0sp", REG_AX, REG_AXY },
{ "subeqysp", REG_AXY, REG_AXY },
{ "subysp", REG_Y, REG_AY },
{ "tosadd0ax", REG_AX, REG_EAXY | REG_TMP1 },
{ "tosadda0", REG_A, REG_AXY },
{ "tosaddax", REG_AX, REG_AXY },
{ "tosaddeax", REG_EAX, REG_EAXY | REG_TMP1 },
{ "tosand0ax", REG_AX, REG_EAXY | REG_TMP1 },
{ "tosanda0", REG_A, REG_AXY },
{ "tosandax", REG_AX, REG_AXY },
{ "tosandeax", REG_EAX, REG_EAXY | REG_TMP1 },
{ "tosaslax", REG_A, REG_AXY | REG_TMP1 },
{ "tosasleax", REG_A, REG_EAXY | REG_TMP1 },
{ "tosasrax", REG_A, REG_AXY | REG_TMP1 },
{ "tosasreax", REG_A, REG_EAXY | REG_TMP1 },
{ "tosdiv0ax", REG_AX, REG_ALL },
{ "tosdiva0", REG_A, REG_ALL },
{ "tosdivax", REG_AX, REG_ALL },
{ "tosdiveax", REG_EAX, REG_ALL },
{ "toseq00", REG_NONE, REG_AXY | REG_SREG },
{ "toseqa0", REG_A, REG_AXY | REG_SREG },
{ "toseqax", REG_AX, REG_AXY | REG_SREG },
{ "toseqeax", REG_EAX, REG_AXY | REG_PTR1 },
{ "tosge00", REG_NONE, REG_AXY | REG_SREG },
{ "tosgea0", REG_A, REG_AXY | REG_SREG },
{ "tosgeax", REG_AX, REG_AXY | REG_SREG },
{ "tosgeeax", REG_EAX, REG_AXY | REG_PTR1 },
{ "tosgt00", REG_NONE, REG_AXY | REG_SREG },
{ "tosgta0", REG_A, REG_AXY | REG_SREG },
{ "tosgtax", REG_AX, REG_AXY | REG_SREG },
{ "tosgteax", REG_EAX, REG_AXY | REG_PTR1 },
{ "tosicmp", REG_AX, REG_AXY | REG_SREG },
{ "tosicmp0", REG_A, REG_AXY | REG_SREG },
{ "toslcmp", REG_EAX, REG_A | REG_Y | REG_PTR1 },
{ "tosle00", REG_NONE, REG_AXY | REG_SREG },
{ "toslea0", REG_A, REG_AXY | REG_SREG },
{ "tosleax", REG_AX, REG_AXY | REG_SREG },
{ "tosleeax", REG_EAX, REG_AXY | REG_PTR1 },
{ "toslt00", REG_NONE, REG_AXY | REG_SREG },
{ "toslta0", REG_A, REG_AXY | REG_SREG },
{ "tosltax", REG_AX, REG_AXY | REG_SREG },
{ "toslteax", REG_EAX, REG_AXY | REG_PTR1 },
{ "tosmod0ax", REG_AX, REG_ALL },
{ "tosmodeax", REG_EAX, REG_ALL },
{ "tosmul0ax", REG_AX, REG_ALL },
{ "tosmula0", REG_A, REG_ALL },
{ "tosmulax", REG_AX, REG_ALL },
{ "tosmuleax", REG_EAX, REG_ALL },
{ "tosne00", REG_NONE, REG_AXY | REG_SREG },
{ "tosnea0", REG_A, REG_AXY | REG_SREG },
{ "tosneax", REG_AX, REG_AXY | REG_SREG },
{ "tosneeax", REG_EAX, REG_AXY | REG_PTR1 },
{ "tosor0ax", REG_AX, REG_EAXY | REG_TMP1 },
{ "tosora0", REG_A, REG_AXY | REG_TMP1 },
{ "tosorax", REG_AX, REG_AXY | REG_TMP1 },
{ "tosoreax", REG_EAX, REG_EAXY | REG_TMP1 },
{ "tosrsub0ax", REG_AX, REG_EAXY | REG_TMP1 },
{ "tosrsuba0", REG_A, REG_AXY | REG_TMP1 },
{ "tosrsubax", REG_AX, REG_AXY | REG_TMP1 },
{ "tosrsubeax", REG_EAX, REG_EAXY | REG_TMP1 },
{ "tosshlax", REG_A, REG_AXY | REG_TMP1 },
{ "tosshleax", REG_A, REG_EAXY | REG_TMP1 },
{ "tosshrax", REG_A, REG_AXY | REG_TMP1 },
{ "tosshreax", REG_A, REG_EAXY | REG_TMP1 },
{ "tossub0ax", REG_AX, REG_EAXY },
{ "tossuba0", REG_A, REG_AXY },
{ "tossubax", REG_AX, REG_AXY },
{ "tossubeax", REG_EAX, REG_EAXY },
{ "tosudiv0ax", REG_AX, REG_ALL & ~REG_SAVE },
{ "tosudiva0", REG_A, REG_EAXY | REG_PTR1 }, /* also ptr4 */
{ "tosudivax", REG_AX, REG_EAXY | REG_PTR1 }, /* also ptr4 */
{ "tosudiveax", REG_EAX, REG_ALL & ~REG_SAVE },
{ "tosuge00", REG_NONE, REG_AXY | REG_SREG },
{ "tosugea0", REG_A, REG_AXY | REG_SREG },
{ "tosugeax", REG_AX, REG_AXY | REG_SREG },
{ "tosugeeax", REG_EAX, REG_AXY | REG_PTR1 },
{ "tosugt00", REG_NONE, REG_AXY | REG_SREG },
{ "tosugta0", REG_A, REG_AXY | REG_SREG },
{ "tosugtax", REG_AX, REG_AXY | REG_SREG },
{ "tosugteax", REG_EAX, REG_AXY | REG_PTR1 },
{ "tosule00", REG_NONE, REG_AXY | REG_SREG },
{ "tosulea0", REG_A, REG_AXY | REG_SREG },
{ "tosuleax", REG_AX, REG_AXY | REG_SREG },
{ "tosuleeax", REG_EAX, REG_AXY | REG_PTR1 },
{ "tosult00", REG_NONE, REG_AXY | REG_SREG },
{ "tosulta0", REG_A, REG_AXY | REG_SREG },
{ "tosultax", REG_AX, REG_AXY | REG_SREG },
{ "tosulteax", REG_EAX, REG_AXY | REG_PTR1 },
{ "tosumod0ax", REG_AX, REG_ALL & ~REG_SAVE },
{ "tosumoda0", REG_A, REG_EAXY | REG_PTR1 }, /* also ptr4 */
{ "tosumodax", REG_AX, REG_EAXY | REG_PTR1 }, /* also ptr4 */
{ "tosumodeax", REG_EAX, REG_ALL & ~REG_SAVE },
{ "tosumul0ax", REG_AX, REG_ALL },
{ "tosumula0", REG_A, REG_ALL },
{ "tosumulax", REG_AX, REG_ALL },
{ "tosumuleax", REG_EAX, REG_ALL },
{ "tosxor0ax", REG_AX, REG_EAXY | REG_TMP1 },
{ "tosxora0", REG_A, REG_AXY | REG_TMP1 },
{ "tosxorax", REG_AX, REG_AXY | REG_TMP1 },
{ "tosxoreax", REG_EAX, REG_EAXY | REG_TMP1 },
{ "tsteax", REG_EAX, REG_Y },
{ "utsteax", REG_EAX, REG_Y },
{ "addeq0sp", REG_AX, PSTATE_ALL | REG_AXY },
{ "addeqysp", REG_AXY, PSTATE_ALL | REG_AXY },
{ "addysp", REG_Y, PSTATE_ALL | REG_NONE },
{ "aslax1", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "aslax2", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "aslax3", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "aslax4", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "aslaxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "asleax1", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "asleax2", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "asleax3", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "asleax4", REG_EAX, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "asrax1", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "asrax2", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "asrax3", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "asrax4", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "asraxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "asreax1", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "asreax2", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "asreax3", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "asreax4", REG_EAX, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "bcasta", REG_A, PSTATE_ALL | REG_AX },
{ "bcastax", REG_AX, PSTATE_ALL | REG_AX },
{ "bcasteax", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "bnega", REG_A, PSTATE_ALL | REG_AX },
{ "bnegax", REG_AX, PSTATE_ALL | REG_AX },
{ "bnegeax", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "booleq", PSTATE_Z, PSTATE_ALL | REG_AX },
{ "boolge", PSTATE_N, PSTATE_ALL | REG_AX },
{ "boolgt", PSTATE_ZN, PSTATE_ALL | REG_AX },
{ "boolle", PSTATE_ZN, PSTATE_ALL | REG_AX },
{ "boollt", PSTATE_N, PSTATE_ALL | REG_AX },
{ "boolne", PSTATE_Z, PSTATE_ALL | REG_AX },
{ "booluge", PSTATE_C, PSTATE_ALL | REG_AX },
{ "boolugt", PSTATE_CZ, PSTATE_ALL | REG_AX },
{ "boolule", PSTATE_CZ, PSTATE_ALL | REG_AX },
{ "boolult", PSTATE_C, PSTATE_ALL | REG_AX },
{ "callax", REG_AX, PSTATE_ALL | REG_ALL },
{ "complax", REG_AX, PSTATE_ALL | REG_AX },
{ "decax1", REG_AX, PSTATE_ALL | REG_AX },
{ "decax2", REG_AX, PSTATE_ALL | REG_AX },
{ "decax3", REG_AX, PSTATE_ALL | REG_AX },
{ "decax4", REG_AX, PSTATE_ALL | REG_AX },
{ "decax5", REG_AX, PSTATE_ALL | REG_AX },
{ "decax6", REG_AX, PSTATE_ALL | REG_AX },
{ "decax7", REG_AX, PSTATE_ALL | REG_AX },
{ "decax8", REG_AX, PSTATE_ALL | REG_AX },
{ "decaxy", REG_AXY, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "deceaxy", REG_EAXY, PSTATE_ALL | REG_EAX },
{ "decsp1", REG_NONE, PSTATE_ALL | REG_Y },
{ "decsp2", REG_NONE, PSTATE_ALL | REG_A },
{ "decsp3", REG_NONE, PSTATE_ALL | REG_A },
{ "decsp4", REG_NONE, PSTATE_ALL | REG_A },
{ "decsp5", REG_NONE, PSTATE_ALL | REG_A },
{ "decsp6", REG_NONE, PSTATE_ALL | REG_A },
{ "decsp7", REG_NONE, PSTATE_ALL | REG_A },
{ "decsp8", REG_NONE, PSTATE_ALL | REG_A },
{ "incax1", REG_AX, PSTATE_ALL | REG_AX },
{ "incax2", REG_AX, PSTATE_ALL | REG_AX },
{ "incax3", REG_AX, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "incax4", REG_AX, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "incax5", REG_AX, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "incax6", REG_AX, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "incax7", REG_AX, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "incax8", REG_AX, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "incaxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "incsp1", REG_NONE, PSTATE_ALL | REG_NONE },
{ "incsp2", REG_NONE, PSTATE_ALL | REG_Y },
{ "incsp3", REG_NONE, PSTATE_ALL | REG_Y },
{ "incsp4", REG_NONE, PSTATE_ALL | REG_Y },
{ "incsp5", REG_NONE, PSTATE_ALL | REG_Y },
{ "incsp6", REG_NONE, PSTATE_ALL | REG_Y },
{ "incsp7", REG_NONE, PSTATE_ALL | REG_Y },
{ "incsp8", REG_NONE, PSTATE_ALL | REG_Y },
{ "laddeq", REG_EAXY|REG_PTR1_LO, PSTATE_ALL | REG_EAXY | REG_PTR1_HI },
{ "laddeq0sp", REG_EAX, PSTATE_ALL | REG_EAXY },
{ "laddeq1", REG_Y | REG_PTR1_LO, PSTATE_ALL | REG_EAXY | REG_PTR1_HI },
{ "laddeqa", REG_AY | REG_PTR1_LO, PSTATE_ALL | REG_EAXY | REG_PTR1_HI },
{ "laddeqysp", REG_EAXY, PSTATE_ALL | REG_EAXY },
{ "ldaidx", REG_AXY, PSTATE_ALL | REG_AX | REG_PTR1 },
{ "ldauidx", REG_AXY, PSTATE_ALL | REG_AX | REG_PTR1 },
{ "ldax0sp", REG_NONE, PSTATE_ALL | REG_AXY },
{ "ldaxi", REG_AX, PSTATE_ALL | REG_AXY | REG_PTR1 },
{ "ldaxidx", REG_AXY, PSTATE_ALL | REG_AXY | REG_PTR1 },
{ "ldaxysp", REG_Y, PSTATE_ALL | REG_AXY },
{ "ldeax0sp", REG_NONE, PSTATE_ALL | REG_EAXY },
{ "ldeaxi", REG_AX, PSTATE_ALL | REG_EAXY | REG_PTR1 },
{ "ldeaxidx", REG_AXY, PSTATE_ALL | REG_EAXY | REG_PTR1 },
{ "ldeaxysp", REG_Y, PSTATE_ALL | REG_EAXY },
{ "leaa0sp", REG_A, PSTATE_ALL | REG_AX },
{ "leaaxsp", REG_AX, PSTATE_ALL | REG_AX },
{ "lsubeq", REG_EAXY|REG_PTR1_LO, PSTATE_ALL | REG_EAXY | REG_PTR1_HI },
{ "lsubeq0sp", REG_EAX, PSTATE_ALL | REG_EAXY },
{ "lsubeq1", REG_Y | REG_PTR1_LO, PSTATE_ALL | REG_EAXY | REG_PTR1_HI },
{ "lsubeqa", REG_AY | REG_PTR1_LO, PSTATE_ALL | REG_EAXY | REG_PTR1_HI },
{ "lsubeqysp", REG_EAXY, PSTATE_ALL | REG_EAXY },
{ "mulax10", REG_AX, PSTATE_ALL | REG_AX | REG_PTR1 },
{ "mulax3", REG_AX, PSTATE_ALL | REG_AX | REG_PTR1 },
{ "mulax5", REG_AX, PSTATE_ALL | REG_AX | REG_PTR1 },
{ "mulax6", REG_AX, PSTATE_ALL | REG_AX | REG_PTR1 },
{ "mulax7", REG_AX, PSTATE_ALL | REG_AX | REG_PTR1 },
{ "mulax9", REG_AX, PSTATE_ALL | REG_AX | REG_PTR1 },
{ "negax", REG_AX, PSTATE_ALL | REG_AX },
{ "push0", REG_NONE, PSTATE_ALL | REG_AXY },
{ "push0ax", REG_AX, PSTATE_ALL | REG_Y | REG_SREG },
{ "push1", REG_NONE, PSTATE_ALL | REG_AXY },
{ "push2", REG_NONE, PSTATE_ALL | REG_AXY },
{ "push3", REG_NONE, PSTATE_ALL | REG_AXY },
{ "push4", REG_NONE, PSTATE_ALL | REG_AXY },
{ "push5", REG_NONE, PSTATE_ALL | REG_AXY },
{ "push6", REG_NONE, PSTATE_ALL | REG_AXY },
{ "push7", REG_NONE, PSTATE_ALL | REG_AXY },
{ "pusha", REG_A, PSTATE_ALL | REG_Y },
{ "pusha0", REG_A, PSTATE_ALL | REG_XY },
{ "pusha0sp", REG_NONE, PSTATE_ALL | REG_AY },
{ "pushaFF", REG_A, PSTATE_ALL | REG_Y },
{ "pushax", REG_AX, PSTATE_ALL | REG_Y },
{ "pushaysp", REG_Y, PSTATE_ALL | REG_AY },
{ "pushc0", REG_NONE, PSTATE_ALL | REG_A | REG_Y },
{ "pushc1", REG_NONE, PSTATE_ALL | REG_A | REG_Y },
{ "pushc2", REG_NONE, PSTATE_ALL | REG_A | REG_Y },
{ "pusheax", REG_EAX, PSTATE_ALL | REG_Y },
{ "pushl0", REG_NONE, PSTATE_ALL | REG_AXY },
{ "pushw", REG_AX, PSTATE_ALL | REG_AXY | REG_PTR1 },
{ "pushw0sp", REG_NONE, PSTATE_ALL | REG_AXY },
{ "pushwidx", REG_AXY, PSTATE_ALL | REG_AXY | REG_PTR1 },
{ "pushwysp", REG_Y, PSTATE_ALL | REG_AXY },
{ "regswap", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "regswap1", REG_XY, PSTATE_ALL | REG_A },
{ "regswap2", REG_XY, PSTATE_ALL | REG_A | REG_Y },
{ "return0", REG_NONE, PSTATE_ALL | REG_AX },
{ "return1", REG_NONE, PSTATE_ALL | REG_AX },
{ "shlax1", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "shlax2", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "shlax3", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "shlax4", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "shlaxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "shleax1", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "shleax2", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "shleax3", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "shleax4", REG_EAX, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "shrax1", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "shrax2", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "shrax3", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "shrax4", REG_AX, PSTATE_ALL | REG_AX | REG_TMP1 },
{ "shraxy", REG_AXY, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "shreax1", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "shreax2", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "shreax3", REG_EAX, PSTATE_ALL | REG_EAX | REG_TMP1 },
{ "shreax4", REG_EAX, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "staspidx", REG_A | REG_Y, PSTATE_ALL | REG_Y | REG_TMP1 | REG_PTR1 },
{ "stax0sp", REG_AX, PSTATE_ALL | REG_Y },
{ "staxspidx", REG_AXY, PSTATE_ALL | REG_TMP1 | REG_PTR1 },
{ "staxysp", REG_AXY, PSTATE_ALL | REG_Y },
{ "steax0sp", REG_EAX, PSTATE_ALL | REG_Y },
{ "steaxysp", REG_EAXY, PSTATE_ALL | REG_Y },
{ "subeq0sp", REG_AX, PSTATE_ALL | REG_AXY },
{ "subeqysp", REG_AXY, PSTATE_ALL | REG_AXY },
{ "subysp", REG_Y, PSTATE_ALL | REG_AY },
{ "tosadd0ax", REG_AX, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "tosadda0", REG_A, PSTATE_ALL | REG_AXY },
{ "tosaddax", REG_AX, PSTATE_ALL | REG_AXY },
{ "tosaddeax", REG_EAX, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "tosand0ax", REG_AX, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "tosanda0", REG_A, PSTATE_ALL | REG_AXY },
{ "tosandax", REG_AX, PSTATE_ALL | REG_AXY },
{ "tosandeax", REG_EAX, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "tosaslax", REG_A, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "tosasleax", REG_A, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "tosasrax", REG_A, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "tosasreax", REG_A, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "tosdiv0ax", REG_AX, PSTATE_ALL | REG_ALL },
{ "tosdiva0", REG_A, PSTATE_ALL | REG_ALL },
{ "tosdivax", REG_AX, PSTATE_ALL | REG_ALL },
{ "tosdiveax", REG_EAX, PSTATE_ALL | REG_ALL },
{ "toseq00", REG_NONE, PSTATE_ALL | REG_AXY | REG_SREG },
{ "toseqa0", REG_A, PSTATE_ALL | REG_AXY | REG_SREG },
{ "toseqax", REG_AX, PSTATE_ALL | REG_AXY | REG_SREG },
{ "toseqeax", REG_EAX, PSTATE_ALL | REG_AXY | REG_PTR1 },
{ "tosge00", REG_NONE, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosgea0", REG_A, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosgeax", REG_AX, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosgeeax", REG_EAX, PSTATE_ALL | REG_AXY | REG_PTR1 },
{ "tosgt00", REG_NONE, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosgta0", REG_A, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosgtax", REG_AX, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosgteax", REG_EAX, PSTATE_ALL | REG_AXY | REG_PTR1 },
{ "tosicmp", REG_AX, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosicmp0", REG_A, PSTATE_ALL | REG_AXY | REG_SREG },
{ "toslcmp", REG_EAX, PSTATE_ALL | REG_A | REG_Y | REG_PTR1 },
{ "tosle00", REG_NONE, PSTATE_ALL | REG_AXY | REG_SREG },
{ "toslea0", REG_A, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosleax", REG_AX, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosleeax", REG_EAX, PSTATE_ALL | REG_AXY | REG_PTR1 },
{ "toslt00", REG_NONE, PSTATE_ALL | REG_AXY | REG_SREG },
{ "toslta0", REG_A, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosltax", REG_AX, PSTATE_ALL | REG_AXY | REG_SREG },
{ "toslteax", REG_EAX, PSTATE_ALL | REG_AXY | REG_PTR1 },
{ "tosmod0ax", REG_AX, PSTATE_ALL | REG_ALL },
{ "tosmodeax", REG_EAX, PSTATE_ALL | REG_ALL },
{ "tosmul0ax", REG_AX, PSTATE_ALL | REG_ALL },
{ "tosmula0", REG_A, PSTATE_ALL | REG_ALL },
{ "tosmulax", REG_AX, PSTATE_ALL | REG_ALL },
{ "tosmuleax", REG_EAX, PSTATE_ALL | REG_ALL },
{ "tosne00", REG_NONE, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosnea0", REG_A, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosneax", REG_AX, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosneeax", REG_EAX, PSTATE_ALL | REG_AXY | REG_PTR1 },
{ "tosor0ax", REG_AX, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "tosora0", REG_A, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "tosorax", REG_AX, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "tosoreax", REG_EAX, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "tosrsub0ax", REG_AX, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "tosrsuba0", REG_A, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "tosrsubax", REG_AX, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "tosrsubeax", REG_EAX, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "tosshlax", REG_A, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "tosshleax", REG_A, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "tosshrax", REG_A, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "tosshreax", REG_A, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "tossub0ax", REG_AX, PSTATE_ALL | REG_EAXY },
{ "tossuba0", REG_A, PSTATE_ALL | REG_AXY },
{ "tossubax", REG_AX, PSTATE_ALL | REG_AXY },
{ "tossubeax", REG_EAX, PSTATE_ALL | REG_EAXY },
{ "tosudiv0ax", REG_AX, PSTATE_ALL | (REG_ALL & ~REG_SAVE) },
{ "tosudiva0", REG_A, PSTATE_ALL | REG_EAXY | REG_PTR1 }, /* also ptr4 */
{ "tosudivax", REG_AX, PSTATE_ALL | REG_EAXY | REG_PTR1 }, /* also ptr4 */
{ "tosudiveax", REG_EAX, PSTATE_ALL | (REG_ALL & ~REG_SAVE) },
{ "tosuge00", REG_NONE, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosugea0", REG_A, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosugeax", REG_AX, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosugeeax", REG_EAX, PSTATE_ALL | REG_AXY | REG_PTR1 },
{ "tosugt00", REG_NONE, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosugta0", REG_A, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosugtax", REG_AX, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosugteax", REG_EAX, PSTATE_ALL | REG_AXY | REG_PTR1 },
{ "tosule00", REG_NONE, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosulea0", REG_A, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosuleax", REG_AX, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosuleeax", REG_EAX, PSTATE_ALL | REG_AXY | REG_PTR1 },
{ "tosult00", REG_NONE, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosulta0", REG_A, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosultax", REG_AX, PSTATE_ALL | REG_AXY | REG_SREG },
{ "tosulteax", REG_EAX, PSTATE_ALL | REG_AXY | REG_PTR1 },
{ "tosumod0ax", REG_AX, PSTATE_ALL | (REG_ALL & ~REG_SAVE) },
{ "tosumoda0", REG_A, PSTATE_ALL | REG_EAXY | REG_PTR1 }, /* also ptr4 */
{ "tosumodax", REG_AX, PSTATE_ALL | REG_EAXY | REG_PTR1 }, /* also ptr4 */
{ "tosumodeax", REG_EAX, PSTATE_ALL | (REG_ALL & ~REG_SAVE) },
{ "tosumul0ax", REG_AX, PSTATE_ALL | REG_ALL },
{ "tosumula0", REG_A, PSTATE_ALL | REG_ALL },
{ "tosumulax", REG_AX, PSTATE_ALL | REG_ALL },
{ "tosumuleax", REG_EAX, PSTATE_ALL | REG_ALL },
{ "tosxor0ax", REG_AX, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "tosxora0", REG_A, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "tosxorax", REG_AX, PSTATE_ALL | REG_AXY | REG_TMP1 },
{ "tosxoreax", REG_EAX, PSTATE_ALL | REG_EAXY | REG_TMP1 },
{ "tsteax", REG_EAX, PSTATE_ALL | REG_Y },
{ "utsteax", REG_EAX, PSTATE_ALL | REG_Y },
};
#define FuncInfoCount (sizeof(FuncInfoTable) / sizeof(FuncInfoTable[0]))
@ -385,10 +385,10 @@ static int CompareFuncInfo (const void* Key, const void* Info)
fncls_t GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg)
fncls_t GetFuncInfo (const char* Name, unsigned int* Use, unsigned int* Chg)
/* For the given function, lookup register information and store it into
** the given variables. If the function is unknown, assume it will use and
** load all registers.
** load all registers as well as touching the processor flags.
*/
{
/* If the function name starts with an underline, it is an external
@ -441,6 +441,9 @@ fncls_t GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg)
/* Will destroy all registers */
*Chg = REG_ALL;
/* and will destroy all processor flags */
*Chg |= PSTATE_ALL;
/* Done */
return FNCLS_GLOBAL;
}
@ -453,6 +456,7 @@ fncls_t GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg)
*/
*Use = REG_ALL;
*Chg = REG_ALL;
*Chg |= PSTATE_ALL;
return FNCLS_NUMERIC;
} else {
@ -477,15 +481,17 @@ fncls_t GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg)
}
*Use = REG_ALL;
*Chg = REG_ALL;
*Chg |= PSTATE_ALL;
}
return FNCLS_BUILTIN;
}
/* Function not found - assume that the primary register is input, and all
** registers are changed
** registers and processor flags are changed
*/
*Use = REG_EAXY;
*Chg = REG_ALL;
*Chg |= PSTATE_ALL;
return FNCLS_UNKNOWN;
}

View File

@ -57,7 +57,7 @@ struct CodeSeg;
/* Forward to struct RegContents */
struct RegContents;
/* Defines for registers. */
/* Defines for registers */
#define REG_NONE 0x0000U
#define REG_A 0x0001U
#define REG_X 0x0002U
@ -74,6 +74,21 @@ struct RegContents;
#define REG_SP_LO 0x1000U
#define REG_SP_HI 0x2000U
/* Defines for some special register usage */
#define SLV_SP65 0x00200000U /* Accesses 6502 stack pointer */
#define SLV_PH65 0x00400000U /* Pushes onto 6502 stack */
#define SLV_PL65 0x00800000U /* Pops from 6502 stack */
/* Defines for processor states */
#define PSTATE_NONE 0x00000000U
#define PSTATE_C 0x01000000U /* Carry */
#define PSTATE_Z 0x02000000U /* Zero */
#define PSTATE_I 0x04000000U /* Interrupt */
#define PSTATE_D 0x08000000U /* Decimal */
#define PSTATE_U 0x10000000U /* Unused */
#define PSTATE_B 0x20000000U /* Break */
#define PSTATE_V 0x40000000U /* Overflow */
#define PSTATE_N 0x80000000U /* Negative */
/* Combined register defines */
#define REG_PTR1 (REG_PTR1_LO | REG_PTR1_HI)
@ -89,6 +104,14 @@ struct RegContents;
#define REG_EAXY (REG_EAX | REG_Y)
#define REG_ZP 0xFFF8U
#define REG_ALL 0xFFFFU
#define PSTATE_CZ (PSTATE_C | PSTATE_Z)
#define PSTATE_CZN (PSTATE_C | PSTATE_Z | PSTATE_N)
#define PSTATE_CZVN (PSTATE_C | PSTATE_Z | PSTATE_V | PSTATE_N)
#define PSTATE_ZN (PSTATE_Z | PSTATE_N)
#define PSTATE_ZVN (PSTATE_Z | PSTATE_V | PSTATE_N)
#define PSTATE_6502 0xE7000000U
#define PSTATE_ALL 0xFF000000U
#define REG_EVERYTHING 0xFFFFFFFFU
@ -139,7 +162,7 @@ typedef enum {
fncls_t GetFuncInfo (const char* Name, unsigned short* Use, unsigned short* Chg);
fncls_t GetFuncInfo (const char* Name, unsigned int* Use, unsigned int* Chg);
/* For the given function, lookup register information and store it into
** the given variables. If the function is unknown, assume it will use and
** load all registers.

View File

@ -1468,6 +1468,7 @@ void CS_GenRegInfo (CodeSeg* S)
/* On entry, the register contents are unknown */
RC_Invalidate (&Regs);
RC_InvalidatePS (&Regs);
CurrentRegs = &Regs;
/* Walk over all insns and note just the changes from one insn to the
@ -1502,6 +1503,7 @@ void CS_GenRegInfo (CodeSeg* S)
Regs = J->RI->Out2;
} else {
RC_Invalidate (&Regs);
RC_InvalidatePS (&Regs);
}
Entry = 1;
} else {
@ -1521,6 +1523,7 @@ void CS_GenRegInfo (CodeSeg* S)
*/
Done = 0;
RC_Invalidate (&Regs);
RC_InvalidatePS (&Regs);
break;
}
if (J->RI->Out2.RegA != Regs.RegA) {
@ -1541,6 +1544,9 @@ void CS_GenRegInfo (CodeSeg* S)
if (J->RI->Out2.Tmp1 != Regs.Tmp1) {
Regs.Tmp1 = UNKNOWN_REGVAL;
}
unsigned PF = J->RI->Out2.PFlags ^ Regs.PFlags;
Regs.PFlags |= ((PF >> 8) | PF | (PF << 8)) & UNKNOWN_PFVAL_ALL;
Regs.ZNRegs &= J->RI->Out2.ZNRegs;
++Entry;
}

File diff suppressed because it is too large Load Diff

View File

@ -320,10 +320,10 @@ static void AdjustLoadInfo (LoadInfo* LI, int Index, int Change)
static int Affected (LoadRegInfo* RI, const CodeEntry* E)
/* Check if the load src may be modified between the pushax and op */
{
fncls_t fncls;
unsigned short Use;
unsigned short Chg;
unsigned short UseToCheck = 0;
fncls_t fncls;
unsigned int Use;
unsigned int Chg;
unsigned int UseToCheck = 0;
if ((RI->Flags & (LI_CHECK_ARG | LI_CHECK_Y)) != 0) {
if (E->AM == AM65_IMM || E->AM == AM65_ACC || E->AM == AM65_IMP || E->AM == AM65_BRA) {

View File

@ -74,6 +74,15 @@ void RC_InvalidateZP (RegContents* C)
void RC_InvalidatePS (RegContents* C)
/* Invalidate processor status */
{
C->PFlags = UNKNOWN_PFVAL_ALL;
C->ZNRegs = ZNREG_NONE;
}
static void RC_Dump1 (FILE* F, const char* Desc, short Val)
/* Dump one register value */
{
@ -102,6 +111,44 @@ void RC_Dump (FILE* F, const RegContents* RC)
#if !defined(HAVE_INLINE)
int PStatesAreKnown (unsigned short PFlags, unsigned WhatStates)
/* Return true if all queried processor states are known.
** Note: WhatStates takes PSTATE_* rather than PFVAL_*.
*/
{
return ((PFlags << (PSTATE_BITS_SHIFT - 8)) & WhatStates & PSTATE_BITS_MASK) == 0;
}
#endif
#if !defined(HAVE_INLINE)
int PStatesAreSet (unsigned short PFlags, unsigned WhatStates)
/* Return true if all queried processor states are known to be set.
** Note: WhatStates takes PSTATE_* rather than PFVAL_*.
*/
{
return (PFlags & (WhatStates >> (PSTATE_BITS_SHIFT - 8))) == 0 &&
(PFlags & (WhatStates >> PSTATE_BITS_SHIFT)) == WhatStates >> PSTATE_BITS_SHIFT;
}
#endif
#if !defined(HAVE_INLINE)
int PStatesAreClear (unsigned short PFlags, unsigned WhatStates)
/* Return true if all queried processor states are known to be cleared.
** Note: WhatStates takes PSTATE_* rather than PFVAL_*.
*/
{
return (PFlags & (WhatStates >> (PSTATE_BITS_SHIFT - 8))) == 0 &&
(PFlags & (WhatStates >> PSTATE_BITS_SHIFT)) == 0;
}
#endif
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
@ -120,6 +167,9 @@ RegInfo* NewRegInfo (const RegContents* RC)
RC_Invalidate (&RI->In);
RC_Invalidate (&RI->Out);
RC_Invalidate (&RI->Out2);
RC_InvalidatePS (&RI->In);
RC_InvalidatePS (&RI->Out);
RC_InvalidatePS (&RI->Out2);
}
/* Return the new struct */

View File

@ -54,6 +54,69 @@
/* Encoding for an unknown register value */
#define UNKNOWN_REGVAL -1
/* Encoding for an unknown processor status:
** For Bit N in the flags, ((flags >> N) & 0x0101) == 0x0101 means 'unknown'
*/
#define UNKNOWN_PFVAL_C 0x0101U /* Carray */
#define UNKNOWN_PFVAL_Z 0x0202U /* Zero */
#define UNKNOWN_PFVAL_I 0x0404U /* Interrupt */
#define UNKNOWN_PFVAL_D 0x0808U /* Decimal */
#define UNKNOWN_PFVAL_U 0x1010U /* Unused */
#define UNKNOWN_PFVAL_B 0x2020U /* Break */
#define UNKNOWN_PFVAL_V 0x4040U /* Overflow */
#define UNKNOWN_PFVAL_N 0x8080U /* Negative */
#define UNKNOWN_PFVAL_CZ (UNKNOWN_PFVAL_C | UNKNOWN_PFVAL_Z)
#define UNKNOWN_PFVAL_CZN (UNKNOWN_PFVAL_N | UNKNOWN_PFVAL_CZ)
#define UNKNOWN_PFVAL_CZVN (UNKNOWN_PFVAL_V | UNKNOWN_PFVAL_CZN)
#define UNKNOWN_PFVAL_ZN (UNKNOWN_PFVAL_Z | UNKNOWN_PFVAL_N)
#define UNKNOWN_PFVAL_ZVN (UNKNOWN_PFVAL_V | UNKNOWN_PFVAL_ZN)
#define UNKNOWN_PFVAL_6502 0xE7E7U
#define UNKNOWN_PFVAL_ALL 0xFFFFU
/* Encoding for a known processor status */
#define PFVAL_C 0x0001U /* Carray set */
#define PFVAL_Z 0x0002U /* Zero set */
#define PFVAL_I 0x0004U /* Interrupt set */
#define PFVAL_D 0x0008U /* Decimal set */
#define PFVAL_U 0x0010U /* Unused set */
#define PFVAL_B 0x0020U /* Break set */
#define PFVAL_V 0x0040U /* Overflow set */
#define PFVAL_N 0x0080U /* Negative set */
#define PFVAL_CZ (PFVAL_C | PFVAL_Z)
#define PFVAL_CZN (PFVAL_N | PFVAL_CZ)
#define PFVAL_CZVN (PFVAL_V | PFVAL_CZN)
#define PFVAL_ZN (PFVAL_Z | PFVAL_N)
#define PFVAL_ZVN (PFVAL_V | PFVAL_ZN)
#define PFVAL_6502 0x00E7U
#define PFVAL_ALL 0x00FFU
/* Used for functions to convert the processor states to processor flags */
#define PSTATE_BITS_SHIFT 24
#define PSTATE_BITS_MASK (0xFFU << PSTATE_BITS_SHIFT)
/* Encoding for unknown Z/N status origin */
#define UNKNOWN_ZNREG 0x0000U
/* Encoding for known register Z/N status origins */
#define ZNREG_NONE 0x0000U /* None */
#define ZNREG_A REG_A
#define ZNREG_X REG_X
#define ZNREG_Y REG_Y
#define ZNREG_TMP1 REG_TMP1
#define ZNREG_PTR1_LO REG_PTR1_LO
#define ZNREG_PTR1_HI REG_PTR1_HI
#define ZNREG_PTR2_LO REG_PTR2_LO
#define ZNREG_PTR2_HI REG_PTR2_HI
#define ZNREG_SREG_LO REG_SREG_LO
#define ZNREG_SREG_HI REG_SREG_HI
#define ZNREG_SAVE_LO REG_SAVE_LO
#define ZNREG_SAVE_HI REG_SAVE_HI
#define ZNREG_AX (REG_A | REG_X)
#define ZNREG_AY (REG_A | REG_Y)
#define ZNREG_AXY (REG_A | REG_X | REG_Y)
/* Register contents */
typedef struct RegContents RegContents;
struct RegContents {
@ -65,6 +128,8 @@ struct RegContents {
short Ptr1Lo;
short Ptr1Hi;
short Tmp1;
unsigned short PFlags; /* Processor flags */
unsigned short ZNRegs; /* Which register(s) the Z/N flags reflect */
};
/* Register change info */
@ -89,6 +154,9 @@ void RC_Invalidate (RegContents* C);
void RC_InvalidateZP (RegContents* C);
/* Invalidate all ZP registers */
void RC_InvalidatePS (RegContents* C);
/* Invalidate processor status */
void RC_Dump (FILE* F, const RegContents* RC);
/* Dump the contents of the given RegContents struct */
@ -112,6 +180,56 @@ INLINE int RegValIsUnknown (short Val)
# define RegValIsUnknown(S) ((S) < 0)
#endif
#if defined(HAVE_INLINE)
INLINE int PStatesAreKnown (unsigned short PFlags, unsigned WhatStates)
/* Return true if all queried processor states are known.
** Note: WhatStates takes PSTATE_* rather than PFVAL_*.
*/
{
return ((PFlags << (PSTATE_BITS_SHIFT - 8)) & WhatStates & PSTATE_BITS_MASK) == 0;
}
#else
int PStatesAreKnown (unsigned short PFlags, unsigned WhatStates);
#endif
#if defined(HAVE_INLINE)
INLINE int PStatesAreUnknown (unsigned short PFlags, unsigned WhatStates)
/* Return true if any queried processor states are unknown.
** Note: WhatStates takes PSTATE_* rather than PFVAL_*.
*/
{
return !PStatesAreKnown (PFlags, WhatStates);
}
#else
# define PStatesAreUnknown(V, B) (!PStatesAreKnown (V, B))
#endif
#if defined(HAVE_INLINE)
INLINE int PStatesAreSet (unsigned short PFlags, unsigned WhatStates)
/* Return true if all queried processor states are known to be set.
** Note: WhatStates takes PSTATE_* rather than PFVAL_*.
*/
{
return (PFlags & (WhatStates >> (PSTATE_BITS_SHIFT - 8))) == 0 &&
(PFlags & (WhatStates >> PSTATE_BITS_SHIFT)) == WhatStates >> PSTATE_BITS_SHIFT;
}
#else
int PStatesAreSet (unsigned short PFlags, unsigned WhatStates);
#endif
#if defined(HAVE_INLINE)
INLINE int PStatesAreClear (unsigned short PFlags, unsigned WhatStates)
/* Return true if the queried processor states are known to be cleared.
** Note: WhatStates takes PSTATE_* rather than PFVAL_*.
*/
{
return (PFlags & (WhatStates >> (PSTATE_BITS_SHIFT - 8))) == 0 &&
(PFlags & (WhatStates >> PSTATE_BITS_SHIFT)) == 0;
}
#else
int PStatesAreClear (unsigned short PFlags, unsigned WhatStates);
#endif
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