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 */ char* Arg; /* Argument as string */
unsigned long Num; /* Numeric argument */ unsigned long Num; /* Numeric argument */
unsigned short Info; /* Additional code info */ unsigned short Info; /* Additional code info */
unsigned short Use; /* Registers used */ unsigned int Use; /* Registers used */
unsigned short Chg; /* Registers changed/destroyed */ unsigned int Chg; /* Registers changed/destroyed */
CodeLabel* JumpTo; /* Jump label */ CodeLabel* JumpTo; /* Jump label */
Collection Labels; /* Labels for this instruction */ Collection Labels; /* Labels for this instruction */
LineInfo* LI; /* Source line info for this insn */ LineInfo* LI; /* Source line info for this insn */

View File

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

View File

@@ -57,7 +57,7 @@ struct CodeSeg;
/* Forward to struct RegContents */ /* Forward to struct RegContents */
struct RegContents; struct RegContents;
/* Defines for registers. */ /* Defines for registers */
#define REG_NONE 0x0000U #define REG_NONE 0x0000U
#define REG_A 0x0001U #define REG_A 0x0001U
#define REG_X 0x0002U #define REG_X 0x0002U
@@ -74,6 +74,21 @@ struct RegContents;
#define REG_SP_LO 0x1000U #define REG_SP_LO 0x1000U
#define REG_SP_HI 0x2000U #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 */ /* Combined register defines */
#define REG_PTR1 (REG_PTR1_LO | REG_PTR1_HI) #define REG_PTR1 (REG_PTR1_LO | REG_PTR1_HI)
@@ -89,6 +104,14 @@ struct RegContents;
#define REG_EAXY (REG_EAX | REG_Y) #define REG_EAXY (REG_EAX | REG_Y)
#define REG_ZP 0xFFF8U #define REG_ZP 0xFFF8U
#define REG_ALL 0xFFFFU #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 /* For the given function, lookup register information and store it into
** the given variables. If the function is unknown, assume it will use and ** the given variables. If the function is unknown, assume it will use and
** load all registers. ** load all registers.

View File

@@ -1468,6 +1468,7 @@ void CS_GenRegInfo (CodeSeg* S)
/* On entry, the register contents are unknown */ /* On entry, the register contents are unknown */
RC_Invalidate (&Regs); RC_Invalidate (&Regs);
RC_InvalidatePS (&Regs);
CurrentRegs = &Regs; CurrentRegs = &Regs;
/* Walk over all insns and note just the changes from one insn to the /* 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; Regs = J->RI->Out2;
} else { } else {
RC_Invalidate (&Regs); RC_Invalidate (&Regs);
RC_InvalidatePS (&Regs);
} }
Entry = 1; Entry = 1;
} else { } else {
@@ -1521,6 +1523,7 @@ void CS_GenRegInfo (CodeSeg* S)
*/ */
Done = 0; Done = 0;
RC_Invalidate (&Regs); RC_Invalidate (&Regs);
RC_InvalidatePS (&Regs);
break; break;
} }
if (J->RI->Out2.RegA != Regs.RegA) { if (J->RI->Out2.RegA != Regs.RegA) {
@@ -1541,6 +1544,9 @@ void CS_GenRegInfo (CodeSeg* S)
if (J->RI->Out2.Tmp1 != Regs.Tmp1) { if (J->RI->Out2.Tmp1 != Regs.Tmp1) {
Regs.Tmp1 = UNKNOWN_REGVAL; 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; ++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) static int Affected (LoadRegInfo* RI, const CodeEntry* E)
/* Check if the load src may be modified between the pushax and op */ /* Check if the load src may be modified between the pushax and op */
{ {
fncls_t fncls; fncls_t fncls;
unsigned short Use; unsigned int Use;
unsigned short Chg; unsigned int Chg;
unsigned short UseToCheck = 0; unsigned int UseToCheck = 0;
if ((RI->Flags & (LI_CHECK_ARG | LI_CHECK_Y)) != 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) { 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) static void RC_Dump1 (FILE* F, const char* Desc, short Val)
/* Dump one register value */ /* 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) RegInfo* NewRegInfo (const RegContents* RC)
/* Allocate a new register info, initialize and return it. If RC is not /* 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 ** 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->In);
RC_Invalidate (&RI->Out); RC_Invalidate (&RI->Out);
RC_Invalidate (&RI->Out2); RC_Invalidate (&RI->Out2);
RC_InvalidatePS (&RI->In);
RC_InvalidatePS (&RI->Out);
RC_InvalidatePS (&RI->Out2);
} }
/* Return the new struct */ /* Return the new struct */

View File

@@ -54,6 +54,69 @@
/* Encoding for an unknown register value */ /* Encoding for an unknown register value */
#define UNKNOWN_REGVAL -1 #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 */ /* Register contents */
typedef struct RegContents RegContents; typedef struct RegContents RegContents;
struct RegContents { struct RegContents {
@@ -65,6 +128,8 @@ struct RegContents {
short Ptr1Lo; short Ptr1Lo;
short Ptr1Hi; short Ptr1Hi;
short Tmp1; short Tmp1;
unsigned short PFlags; /* Processor flags */
unsigned short ZNRegs; /* Which register(s) the Z/N flags reflect */
}; };
/* Register change info */ /* Register change info */
@@ -89,6 +154,9 @@ void RC_Invalidate (RegContents* C);
void RC_InvalidateZP (RegContents* C); void RC_InvalidateZP (RegContents* C);
/* Invalidate all ZP registers */ /* Invalidate all ZP registers */
void RC_InvalidatePS (RegContents* C);
/* Invalidate processor status */
void RC_Dump (FILE* F, const RegContents* RC); void RC_Dump (FILE* F, const RegContents* RC);
/* Dump the contents of the given RegContents struct */ /* Dump the contents of the given RegContents struct */
@@ -112,6 +180,56 @@ INLINE int RegValIsUnknown (short Val)
# define RegValIsUnknown(S) ((S) < 0) # define RegValIsUnknown(S) ((S) < 0)
#endif #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); RegInfo* NewRegInfo (const RegContents* RC);
/* Allocate a new register info, initialize and return it. If RC is not /* 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 ** a NULL pointer, it is used to initialize both, the input and output