From 6617a017faa43382bd2bebb40a3e8f810d35f6b6 Mon Sep 17 00:00:00 2001 From: acqn Date: Fri, 5 Feb 2021 17:29:49 +0800 Subject: [PATCH 1/2] Added Opt_a_tossub for 8-bit subtraction. --- src/cc65/coptstop.c | 53 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index ae40a55e9..13470dc18 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -1292,6 +1292,58 @@ static unsigned Opt_a_tosne (StackOpData* D) +static unsigned Opt_a_tossub (StackOpData* D) +/* Optimize the tossubax sequence. */ +{ + CodeEntry* X; + + + /* Inline the sbc */ + D->IP = D->OpIndex+1; + + /* Must be true because of OP_RHS_LOAD */ + CHECK ((D->Rhs.A.Flags & D->Rhs.X.Flags & LI_DIRECT) != 0); + + /* sec */ + X = NewCodeEntry (OP65_SEC, AM65_IMP, 0, 0, D->OpEntry->LI); + InsertEntry (D, X, D->IP++); + + /* Add code for low operand */ + AddOpLow (D, OP65_SBC, &D->Rhs); + + /* Do sign-extension as high-byte operation only when its result is used */ + if ((GetRegInfo (D->Code, D->IP, REG_X) & REG_X) != 0) { + CodeLabel* L; + CodeEntry* N; + + X = NewCodeEntry (OP65_LDX, AM65_IMM, MakeHexArg (0), 0, D->OpEntry->LI); + InsertEntry (D, X, D->IP++); + + /* Add sign extension - N is unused now */ + N = CS_GetEntry (D->Code, D->IP); + CHECK (N != 0); + L = CS_GenLabel (D->Code, N); + + X = NewCodeEntry (OP65_BCS, AM65_BRA, L->Name, L, D->OpEntry->LI); + InsertEntry (D, X, D->IP++); + + X = NewCodeEntry (OP65_DEX, AM65_IMP, 0, 0, D->OpEntry->LI); + InsertEntry (D, X, D->IP++); + } + + /* Rhs load entries must be removed */ + D->Rhs.X.Flags |= LI_REMOVE; + D->Rhs.A.Flags |= LI_REMOVE; + + /* Remove the push and the call to the tossubax function */ + RemoveRemainders (D); + + /* We changed the sequence */ + return 1; +} + + + static unsigned Opt_a_tosuge (StackOpData* D) /* Optimize the tosgeax and tosugeax sequences */ { @@ -1363,6 +1415,7 @@ static const OptFuncDesc FuncRegATable[] = { { "tosleax", Opt_a_tosule, REG_NONE, OP_NONE }, { "tosltax", Opt_a_tosult, REG_NONE, OP_NONE }, { "tosneax", Opt_a_tosne, REG_NONE, OP_NONE }, + { "tossubax", Opt_a_tossub, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT }, { "tosugeax", Opt_a_tosuge, REG_NONE, OP_NONE }, { "tosugtax", Opt_a_tosugt, REG_NONE, OP_NONE }, { "tosuleax", Opt_a_tosule, REG_NONE, OP_NONE }, From 8b6d78a075dafde8583c4992d37995d9b4c9db97 Mon Sep 17 00:00:00 2001 From: acqn Date: Mon, 1 Mar 2021 22:11:22 +0800 Subject: [PATCH 2/2] Added Opt_a_tosbitwise for 8-bit bitwise operations. --- src/cc65/coptstop.c | 83 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) diff --git a/src/cc65/coptstop.c b/src/cc65/coptstop.c index 13470dc18..7e024ae88 100644 --- a/src/cc65/coptstop.c +++ b/src/cc65/coptstop.c @@ -1105,6 +1105,62 @@ static unsigned Opt_tosxorax (StackOpData* D) +static unsigned Opt_a_tosbitwise (StackOpData* D, opc_t OPC) +/* Optimize the tosandax/tosorax/tosxorax sequence. */ +{ + CodeEntry* X; + + + /* Inline the bitwise operation */ + D->IP = D->OpIndex+1; + + /* Backup lhs if necessary */ + if ((D->Rhs.A.Flags & LI_DIRECT) == 0) { + if ((D->Lhs.A.Flags & (LI_DIRECT | LI_RELOAD_Y)) == LI_DIRECT) { + /* Just reload lhs */ + X = NewCodeEntry (OPC, D->Lhs.A.LoadEntry->AM, D->Lhs.A.LoadEntry->Arg, 0, D->OpEntry->LI); + InsertEntry (D, X, D->IP++); + } else { + /* Backup lhs */ + X = NewCodeEntry (OP65_STA, AM65_ZP, D->ZPLo, 0, D->PushEntry->LI); + InsertEntry (D, X, D->PushIndex+1); + /* Add code for low operand */ + X = NewCodeEntry (OPC, AM65_ZP, D->ZPLo, 0, D->OpEntry->LI); + InsertEntry (D, X, D->IP++); + } + } else { + /* Add code for low operand */ + X = NewCodeEntry (OPC, D->Rhs.A.LoadEntry->AM, D->Rhs.A.LoadEntry->Arg, 0, D->OpEntry->LI); + InsertEntry (D, X, D->IP++); + + /* Rhs load entries may be removed */ + D->Rhs.A.Flags |= LI_REMOVE; + } + + /* Do high-byte operation only when its result is used */ + if ((GetRegInfo (D->Code, D->IP, REG_X) & REG_X) != 0) { + /* Replace the high-byte load with 0 for EOR, or just leave it alone */ + if (OPC == OP65_EOR) { + X = NewCodeEntry (OP65_LDX, AM65_IMM, MakeHexArg (0), 0, D->Rhs.X.ChgEntry->LI); + InsertEntry (D, X, D->IP++); + D->Rhs.X.Flags |= LI_REMOVE; + } else { + D->Rhs.X.Flags |= LI_DONT_REMOVE; + } + } else { + /* Rhs load entries may be removed */ + D->Rhs.X.Flags |= LI_REMOVE; + } + + /* Remove the push and the call to the tossubax function */ + RemoveRemainders (D); + + /* We changed the sequence */ + return 1; +} + + + static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer) /* Optimize the TOS compare sequence with a bool transformer */ { @@ -1177,6 +1233,14 @@ static unsigned Opt_a_toscmpbool (StackOpData* D, const char* BoolTransformer) +static unsigned Opt_a_tosand (StackOpData* D) +/* Optimize the tosandax sequence. */ +{ + return Opt_a_tosbitwise (D, OP65_AND); +} + + + static unsigned Opt_a_toseq (StackOpData* D) /* Optimize the toseqax sequence */ { @@ -1292,6 +1356,14 @@ static unsigned Opt_a_tosne (StackOpData* D) +static unsigned Opt_a_tosor (StackOpData* D) +/* Optimize the tosorax sequence. */ +{ + return Opt_a_tosbitwise (D, OP65_ORA); +} + + + static unsigned Opt_a_tossub (StackOpData* D) /* Optimize the tossubax sequence. */ { @@ -1376,6 +1448,14 @@ static unsigned Opt_a_tosult (StackOpData* D) +static unsigned Opt_a_tosxor (StackOpData* D) +/* Optimize the tosxorax sequence. */ +{ + return Opt_a_tosbitwise (D, OP65_EOR); +} + + + /*****************************************************************************/ /* Code */ /*****************************************************************************/ @@ -1408,6 +1488,7 @@ static const OptFuncDesc FuncTable[] = { }; static const OptFuncDesc FuncRegATable[] = { + { "tosandax", Opt_a_tosand, REG_NONE, OP_NONE }, { "toseqax", Opt_a_toseq, REG_NONE, OP_NONE }, { "tosgeax", Opt_a_tosuge, REG_NONE, OP_NONE }, { "tosgtax", Opt_a_tosugt, REG_NONE, OP_NONE }, @@ -1415,11 +1496,13 @@ static const OptFuncDesc FuncRegATable[] = { { "tosleax", Opt_a_tosule, REG_NONE, OP_NONE }, { "tosltax", Opt_a_tosult, REG_NONE, OP_NONE }, { "tosneax", Opt_a_tosne, REG_NONE, OP_NONE }, + { "tosorax", Opt_a_tosor, REG_NONE, OP_NONE }, { "tossubax", Opt_a_tossub, REG_NONE, OP_RHS_REMOVE_DIRECT | OP_RHS_LOAD_DIRECT }, { "tosugeax", Opt_a_tosuge, REG_NONE, OP_NONE }, { "tosugtax", Opt_a_tosugt, REG_NONE, OP_NONE }, { "tosuleax", Opt_a_tosule, REG_NONE, OP_NONE }, { "tosultax", Opt_a_tosult, REG_NONE, OP_NONE }, + { "tosxorax", Opt_a_tosxor, REG_NONE, OP_NONE }, }; #define FUNC_COUNT(Table) (sizeof(Table) / sizeof(Table[0]))