From 2324bd62f6e55084d6d763f6c3a8a9b7bfd5c876 Mon Sep 17 00:00:00 2001 From: acqn Date: Tue, 8 Jun 2021 14:16:14 +0800 Subject: [PATCH] If __A__,__AX__ or __EAX__ is used, post-inc/dec within the same statement will not modify it. Moved testcase from src/test/todo to src/test/val plus minor improvement on portability. --- src/cc65.vcxproj | 2 + src/cc65/expr.c | 60 +++++++++++++++--------- src/cc65/expr.h | 5 -- src/cc65/goto.c | 1 + src/cc65/initdata.c | 1 + src/cc65/locals.c | 1 + src/cc65/seqpoint.c | 67 ++++++++++++++++++++++++++ src/cc65/seqpoint.h | 70 ++++++++++++++++++++++++++++ src/cc65/stdfunc.c | 1 + src/cc65/stmt.c | 27 ++++++++--- src/cc65/testexpr.c | 1 + test/{todo => val}/inline-asm-1489.c | 22 ++++++++- 12 files changed, 222 insertions(+), 36 deletions(-) create mode 100644 src/cc65/seqpoint.c create mode 100644 src/cc65/seqpoint.h rename test/{todo => val}/inline-asm-1489.c (83%) diff --git a/src/cc65.vcxproj b/src/cc65.vcxproj index 7e2e8ea8c..556c616b0 100644 --- a/src/cc65.vcxproj +++ b/src/cc65.vcxproj @@ -110,6 +110,7 @@ + @@ -190,6 +191,7 @@ + diff --git a/src/cc65/expr.c b/src/cc65/expr.c index 37af494b5..61a24329f 100644 --- a/src/cc65/expr.c +++ b/src/cc65/expr.c @@ -31,6 +31,7 @@ #include "macrotab.h" #include "preproc.h" #include "scanner.h" +#include "seqpoint.h" #include "shiftexpr.h" #include "stackptr.h" #include "standard.h" @@ -677,6 +678,7 @@ void DoDeferred (unsigned Flags, ExprDesc* Expr) int I; unsigned Size = 0; int Count = GetDeferredOpCount (); + unsigned StmtFlags = GetSQPFlags (); /* Nothing to be done */ if (Count <= 0) { @@ -684,26 +686,38 @@ void DoDeferred (unsigned Flags, ExprDesc* Expr) } /* Backup some regs/processor flags around the inc/dec */ - if ((Flags & SQP_KEEP_TEST) != 0 && ED_NeedsTest (Expr)) { + if ((StmtFlags & SQP_KEEP_TEST) != 0 || + ((Flags & SQP_KEEP_TEST) != 0 && ED_NeedsTest (Expr))) { /* Sufficient to add a pair of PHP/PLP for all cases */ AddCodeLine ("php"); } - /* Backup the content of EAX around the inc/dec */ - if ((Flags & SQP_KEEP_EAX) != 0 && ED_NeedsPrimary (Expr)) { - /* Get the size */ - Size = CheckedSizeOf (Expr->Type); + if ((Flags & SQP_MASK_EAX) != 0 && ED_NeedsPrimary (Expr)) { + Size = SizeOf (Expr->Type); + } - if (Size < 2) { - AddCodeLine ("pha"); - } else if (Size < 3) { - AddCodeLine ("sta regsave"); - AddCodeLine ("stx regsave+1"); - } else { - AddCodeLine ("jsr saveeax"); + /* Get the size of the backup */ + if ((StmtFlags & SQP_MASK_EAX) != 0) { + switch (StmtFlags & SQP_MASK_EAX) { + case SQP_KEEP_A: if (Size < 1) Size = 1; break; + case SQP_KEEP_AX: if (Size < 2) Size = 2; break; + case SQP_KEEP_EAX: if (Size < 4) Size = 4; break; + default: ; } } + /* Backup the content of EAX around the inc/dec */ + if (Size == 1) { + AddCodeLine ("pha"); + } else if (Size == 2) { + AddCodeLine ("sta regsave"); + AddCodeLine ("stx regsave+1"); + } else if (Size == 3 || Size == 4) { + AddCodeLine("jsr saveeax"); + } else if (Size > 4) { + Error ("Unsupported deferred operand size: %u", Size); + } + for (I = 0; I < Count; ++I) { DeferredOp* Op = CollAtUnchecked (&DeferredOps, I); switch (Op->OpType) { @@ -721,19 +735,18 @@ void DoDeferred (unsigned Flags, ExprDesc* Expr) CollDeleteAll (&DeferredOps); /* Restore the content of EAX around the inc/dec */ - if ((Flags & SQP_KEEP_EAX) != 0 && ED_NeedsPrimary (Expr)) { - if (Size < 2) { - AddCodeLine ("pla"); - } else if (Size < 3) { - AddCodeLine ("lda regsave"); - AddCodeLine ("ldx regsave+1"); - } else { - AddCodeLine ("jsr resteax"); - } + if (Size == 1) { + AddCodeLine ("pla"); + } else if (Size == 2) { + AddCodeLine ("lda regsave"); + AddCodeLine ("ldx regsave+1"); + } else if (Size == 3 || Size == 4) { + AddCodeLine ("jsr resteax"); } /* Restore the regs/processor flags around the inc/dec */ - if ((Flags & SQP_KEEP_TEST) != 0 && ED_NeedsTest (Expr)) { + if ((StmtFlags & SQP_KEEP_TEST) != 0 || + ((Flags & SQP_KEEP_TEST) != 0 && ED_NeedsTest (Expr))) { /* Sufficient to pop the processor flags */ AddCodeLine ("plp"); } @@ -1362,6 +1375,7 @@ static void Primary (ExprDesc* E) case TOK_A: /* Register pseudo variable */ + SetSQPFlags (SQP_KEEP_A); E->Type = type_uchar; E->Flags = E_LOC_PRIMARY | E_RTYPE_LVAL; NextToken (); @@ -1369,6 +1383,7 @@ static void Primary (ExprDesc* E) case TOK_AX: /* Register pseudo variable */ + SetSQPFlags (SQP_KEEP_AX); E->Type = type_uint; E->Flags = E_LOC_PRIMARY | E_RTYPE_LVAL; NextToken (); @@ -1376,6 +1391,7 @@ static void Primary (ExprDesc* E) case TOK_EAX: /* Register pseudo variable */ + SetSQPFlags (SQP_KEEP_EAX); E->Type = type_ulong; E->Flags = E_LOC_PRIMARY | E_RTYPE_LVAL; NextToken (); diff --git a/src/cc65/expr.h b/src/cc65/expr.h index 5644fb82d..8bf7c00b5 100644 --- a/src/cc65/expr.h +++ b/src/cc65/expr.h @@ -23,11 +23,6 @@ -#define SQP_KEEP_NONE 0x00 -#define SQP_KEEP_TEST 0x01U -#define SQP_KEEP_EAX 0x02U -#define SQP_KEEP_EXPR 0x03U /* SQP_KEEP_TEST | SQP_KEEP_EAX */ - /* Generator attributes */ #define GEN_NOPUSH 0x01 /* Don't push lhs */ #define GEN_COMM 0x02 /* Operator is commutative */ diff --git a/src/cc65/goto.c b/src/cc65/goto.c index 7d3ff1a6a..44ae0595e 100644 --- a/src/cc65/goto.c +++ b/src/cc65/goto.c @@ -43,6 +43,7 @@ #include "expr.h" #include "loadexpr.h" #include "scanner.h" +#include "seqpoint.h" #include "standard.h" #include "symtab.h" #include "goto.h" diff --git a/src/cc65/initdata.c b/src/cc65/initdata.c index f63e9e95c..f576c0255 100644 --- a/src/cc65/initdata.c +++ b/src/cc65/initdata.c @@ -58,6 +58,7 @@ #include "litpool.h" #include "pragma.h" #include "scanner.h" +#include "seqpoint.h" #include "shift.h" #include "standard.h" #include "symtab.h" diff --git a/src/cc65/locals.c b/src/cc65/locals.c index 68ac00e62..7bc5697ff 100644 --- a/src/cc65/locals.c +++ b/src/cc65/locals.c @@ -49,6 +49,7 @@ #include "initdata.h" #include "loadexpr.h" #include "locals.h" +#include "seqpoint.h" #include "stackptr.h" #include "standard.h" #include "staticassert.h" diff --git a/src/cc65/seqpoint.c b/src/cc65/seqpoint.c new file mode 100644 index 000000000..a6d992113 --- /dev/null +++ b/src/cc65/seqpoint.c @@ -0,0 +1,67 @@ +/*****************************************************************************/ +/* */ +/* seqpoint.h */ +/* */ +/* Stuff involved in sequence points */ +/* */ +/* */ +/* */ +/* Copyright 2022 The cc65 Authors */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +/* cc65 */ +#include "seqpoint.h" + + + +/*****************************************************************************/ +/* data */ +/*****************************************************************************/ + + + +/* Remeber if __A__, __AX__ and __EAX__ are being used */ +unsigned PendingSqpFlags = SQP_KEEP_NONE; + + + +/*****************************************************************************/ +/* code */ +/*****************************************************************************/ + + + +void SetSQPFlags (unsigned Flags) +/* Set the SQP_KEEP_* flags for the deferred operations in the statement */ +{ + PendingSqpFlags = Flags; +} + + + +unsigned GetSQPFlags (void) +/* Get the SQP_KEEP_* flags for the deferred operations in the statement */ +{ + return PendingSqpFlags; +} diff --git a/src/cc65/seqpoint.h b/src/cc65/seqpoint.h new file mode 100644 index 000000000..07ff0d315 --- /dev/null +++ b/src/cc65/seqpoint.h @@ -0,0 +1,70 @@ +/*****************************************************************************/ +/* */ +/* seqpoint.h */ +/* */ +/* Stuff involved in sequence points */ +/* */ +/* */ +/* */ +/* Copyright 2022 The cc65 Authors */ +/* */ +/* */ +/* This software is provided 'as-is', without any expressed or implied */ +/* warranty. In no event will the authors be held liable for any damages */ +/* arising from the use of this software. */ +/* */ +/* Permission is granted to anyone to use this software for any purpose, */ +/* including commercial applications, and to alter it and redistribute it */ +/* freely, subject to the following restrictions: */ +/* */ +/* 1. The origin of this software must not be misrepresented; you must not */ +/* claim that you wrote the original software. If you use this software */ +/* in a product, an acknowledgment in the product documentation would be */ +/* appreciated but is not required. */ +/* 2. Altered source versions must be plainly marked as such, and must not */ +/* be misrepresented as being the original software. */ +/* 3. This notice may not be removed or altered from any source */ +/* distribution. */ +/* */ +/*****************************************************************************/ + + + +#ifndef SEQPOINT_H +#define SEQPOINT_H + + + +/*****************************************************************************/ +/* data */ +/*****************************************************************************/ + + + +#define SQP_KEEP_NONE 0x00U +#define SQP_KEEP_A 0x01U +#define SQP_KEEP_AX 0x03U +#define SQP_KEEP_EAX 0x07U +#define SQP_MASK_EAX 0x07U +#define SQP_KEEP_TEST 0x10U +#define SQP_KEEP_EXPR 0x17U /* SQP_KEEP_TEST | SQP_KEEP_EAX */ + + + +/*****************************************************************************/ +/* code */ +/*****************************************************************************/ + + + +void SetSQPFlags (unsigned Flags); +/* Set the SQP_KEEP_* flags for the deferred operations in the statement */ + +unsigned GetSQPFlags (void); +/* Get the SQP_KEEP_* flags for the deferred operations in the statement */ + + + +/* End of seqpoint.h */ + +#endif diff --git a/src/cc65/stdfunc.c b/src/cc65/stdfunc.c index d22c73dcf..e968aaf1f 100644 --- a/src/cc65/stdfunc.c +++ b/src/cc65/stdfunc.c @@ -50,6 +50,7 @@ #include "litpool.h" #include "loadexpr.h" #include "scanner.h" +#include "seqpoint.h" #include "stackptr.h" #include "stdfunc.h" #include "stdnames.h" diff --git a/src/cc65/stmt.c b/src/cc65/stmt.c index 7355e88a8..613129e1b 100644 --- a/src/cc65/stmt.c +++ b/src/cc65/stmt.c @@ -56,6 +56,7 @@ #include "loop.h" #include "pragma.h" #include "scanner.h" +#include "seqpoint.h" #include "stackptr.h" #include "stmt.h" #include "swstmt.h" @@ -674,6 +675,8 @@ int AnyStatement (int* PendingToken) ** NULL, the function will skip the token. */ { + int GotBreak = 0; + /* Assume no pending token */ if (PendingToken) { *PendingToken = 0; @@ -689,7 +692,8 @@ int AnyStatement (int* PendingToken) switch (CurTok.Tok) { case TOK_IF: - return IfStatement (); + GotBreak = IfStatement (); + break; case TOK_SWITCH: SwitchStatement (); @@ -710,22 +714,26 @@ int AnyStatement (int* PendingToken) case TOK_GOTO: GotoStatement (); CheckSemi (PendingToken); - return 1; + GotBreak = 1; + break; case TOK_RETURN: ReturnStatement (); CheckSemi (PendingToken); - return 1; + GotBreak = 1; + break; case TOK_BREAK: BreakStatement (); CheckSemi (PendingToken); - return 1; + GotBreak = 1; + break; case TOK_CONTINUE: ContinueStatement (); CheckSemi (PendingToken); - return 1; + GotBreak = 1; + break; case TOK_PRAGMA: DoPragma (); @@ -737,12 +745,17 @@ int AnyStatement (int* PendingToken) break; case TOK_LCURLY: - return CompoundStatement (PendingToken); + GotBreak = CompoundStatement (PendingToken); + break; default: /* Simple statement */ Statement (PendingToken); break; } - return 0; + + /* Reset SQP flags */ + SetSQPFlags (SQP_KEEP_NONE); + + return GotBreak; } diff --git a/src/cc65/testexpr.c b/src/cc65/testexpr.c index bad8b95f1..14160f13f 100644 --- a/src/cc65/testexpr.c +++ b/src/cc65/testexpr.c @@ -39,6 +39,7 @@ #include "expr.h" #include "loadexpr.h" #include "scanner.h" +#include "seqpoint.h" #include "testexpr.h" diff --git a/test/todo/inline-asm-1489.c b/test/val/inline-asm-1489.c similarity index 83% rename from test/todo/inline-asm-1489.c rename to test/val/inline-asm-1489.c index 57699ab0a..a531c7405 100644 --- a/test/todo/inline-asm-1489.c +++ b/test/val/inline-asm-1489.c @@ -1,9 +1,11 @@ +#include #include #include #include #include +#ifdef __CC65__ #define testasm1(C) (__AX__ = (C), \ asm("and #$3f"),\ __AX__) @@ -11,6 +13,22 @@ #define testasm2(C) (__A__ = (C), \ asm("and #$3f"),\ __A__) +#else +/* Non-cc65 compiler. Just make the code compile and work. */ +uint16_t testasm1(uint16_t C) +{ + uint16_t AX = C; + AX &= 0x3f; + return AX; +} + +uint8_t testasm2(uint8_t C) +{ + uint8_t A = C; + A &= 0x3f; + return A; +} +#endif uint8_t src[32] = { 0x10, 0x41, 0x62, 0x83, 0xb4, 0xf5, 0xe6, 0xc7, 0, 0 }; uint8_t src2[32] = { 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0, 0 }; @@ -46,7 +64,7 @@ void dotest1b(uint8_t *s, uint8_t *d) void dotest2a (void) { char *p = &src2[0]; - uint16_t scaddr=&dest[0]; //output to line 11 on the screen + uintptr_t scaddr=&dest[0]; //output to line 11 on the screen printf("dotest2a\n"); while (*p != 0) { @@ -58,7 +76,7 @@ void dotest2a (void) void dotest2b (void) { char *p = &src2[0]; - uint16_t scaddr=&dest[0]; //output to line 11 on the screen + uintptr_t scaddr=&dest[0]; //output to line 11 on the screen printf("dotest2b\n"); while (*p != 0) {