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:
parent
494bf10e80
commit
2324bd62f6
@ -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" />
|
||||
|
@ -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 ();
|
||||
|
@ -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 */
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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
67
src/cc65/seqpoint.c
Normal 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
70
src/cc65/seqpoint.h
Normal 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
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "expr.h"
|
||||
#include "loadexpr.h"
|
||||
#include "scanner.h"
|
||||
#include "seqpoint.h"
|
||||
#include "testexpr.h"
|
||||
|
||||
|
||||
|
@ -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) {
|
Loading…
Reference in New Issue
Block a user