1
0
mirror of https://github.com/cc65/cc65.git synced 2024-11-18 00:07:21 +00:00

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.
This commit is contained in:
acqn 2021-06-08 14:16:14 +08:00
parent 494bf10e80
commit 2324bd62f6
12 changed files with 222 additions and 36 deletions

View File

@ -110,6 +110,7 @@
<ClInclude Include="cc65\scanner.h" />
<ClInclude Include="cc65\scanstrbuf.h" />
<ClInclude Include="cc65\segments.h" />
<ClInclude Include="cc65\seqpoint.h" />
<ClInclude Include="cc65\shiftexpr.h" />
<ClInclude Include="cc65\stackptr.h" />
<ClInclude Include="cc65\standard.h" />
@ -190,6 +191,7 @@
<ClCompile Include="cc65\scanner.c" />
<ClCompile Include="cc65\scanstrbuf.c" />
<ClCompile Include="cc65\segments.c" />
<ClCompile Include="cc65\seqpoint.c" />
<ClCompile Include="cc65\shiftexpr.c" />
<ClCompile Include="cc65\stackptr.c" />
<ClCompile Include="cc65\standard.c" />

View File

@ -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 ();

View File

@ -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 */

View File

@ -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"

View File

@ -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"

View File

@ -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"

67
src/cc65/seqpoint.c Normal file
View File

@ -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;
}

70
src/cc65/seqpoint.h Normal file
View File

@ -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

View File

@ -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"

View File

@ -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;
}

View File

@ -39,6 +39,7 @@
#include "expr.h"
#include "loadexpr.h"
#include "scanner.h"
#include "seqpoint.h"
#include "testexpr.h"

View File

@ -1,9 +1,11 @@
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#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) {