[ below.
- Using ]
-
- - You may not use names of standard C functions in your own code. If you
- do that, your program is not standard compliant anyway, but using
-
- - The inlined string and memory functions will not handle strings or
- memory areas larger than 255 bytes. Similarly, the inlined
-
-
+ Using
+
Input and output
The compiler will accept one C file per invocation and create a file with
@@ -556,21 +591,21 @@ and the one defined by the ISO standard:
-- The datatypes "float" and "double" are not available.
-
-- C Functions may not return structs (or unions), and structs may not
+
- The datatypes "float" and "double" are not available.
+
+- C Functions may not return structs (or unions), and structs may not
be passed as parameters by value. However, struct assignment *is*
- possible.
-
-- Most of the C library is available with only the fastcall calling
- convention (
[). It means
- that you must not mix pointers to those functions with pointers to
- user-written, cdecl functions (the calling conventions are incompatible).
- ]
-- The
+- Most of the C library is available with only the fastcall calling
+ convention (
[). It means
+ that you must not mix pointers to those functions with pointers to
+ user-written, cdecl functions (the calling conventions are incompatible).
+ ]
+- The
+
There may be some more minor differences I'm currently not aware of. The
@@ -585,49 +620,48 @@ This cc65 version has some extensions to the ISO C standard.
-- The compiler allows to insert assembler statements into the output
- file. The syntax is
+
- The compiler allows to insert assembler statements into the output
+ file. The syntax is
-
- asm [optional volatile] (<string literal>[, optional parameters]) ;
-
- or
-
+
+ asm [optional volatile] (<string literal>[, optional parameters]) ;
+
+ or
+
__asm__ [optional volatile] (<string literal>[, optional parameters]) ;
-
+
- The first form is in the user namespace; and, is disabled if the .
-
+ There is a whole section covering inline assembler statements,
+ [.
+ ]
-- The normal calling convention -- for non-variadic functions -- is
- named "fastcall". The syntax for a function declaration that
-
- <return type> fastcall <function name> (<parameter list>)
-
- or
-
- <return type> __fastcall__ <function name> (<parameter list>)
-
- An example is
-
- void __fastcall__ f (unsigned char c)
-
- The first form of the fastcall keyword is in the user namespace and can
- therefore be disabled with the [ The normal calling convention -- for non-variadic functions -- is
+ named "fastcall". The syntax for a function declaration that
+ ]
+ <return type> fastcall <function name> (<parameter list>)
+
+ or
+
+ <return type> __fastcall__ <function name> (<parameter list>)
+
+ An example is
+
+ void __fastcall__ f (unsigned char c)
+
+ The first form of the fastcall keyword is in the user namespace and can
+ therefore be disabled with the command line option.
- For functions that are
-
+ For functions that are
- There is another calling convention named "cdecl". Variadic functions
(their prototypes have an ellipsis [
+ places.
-- There are two pseudo variables named
There are two pseudo variables named
- #define hi(x) \
+
+ #define hi(x) \
(__AX__ = (x), \
asm ("txa"), \
asm ("ldx #$00"), \
__AX__)
-
+
- will give the high byte of any unsigned value.
-
+ will give the high byte of any unsigned value.
+
-- Inside a function, the identifier
Inside a function, the identifier
- #define PRINT_DEBUG(s) printf ("%s: %s\n", __func__, s);
-
+
+ #define PRINT_DEBUG(s) printf ("%s: %s\n", __func__, s);
+
- The macro will print the name of the current function plus a given
- string.
-
+ The macro will print the name of the current function plus a given
+ string.
+
- cc65 allows the initialization of
__EAGERLY_INLINE_FUNCS__
+
+ Is defined if the compiler was called with the __FILE__
This macro expands to a string containing the name of the C source file.
@@ -912,6 +951,7 @@ The compiler defines several macros at startup:
+
#pragmas
The compiler understands some pragmas that may be used to change code
@@ -920,6 +960,19 @@ If the first parameter is #pragma allow-eager-inline ([push,] on|off)
+
+ Allow eager inlining of known functions. If the argument is "off", eager
+ inlining is disabled, otherwise it is enabled. Please note that (in contrast
+ to the #pragma bss-name ([push,] <name>)
This pragma changes the name used for the BSS segment (the BSS segment
@@ -938,7 +991,7 @@ parameter with the
- #pragma bss-name ("MyBSS")
+ #pragma bss-name ("MyBSS")
@@ -993,6 +1046,7 @@ parameter with the #pragma code-name ([push,] <name>)
This pragma changes the name used for the CODE segment (the CODE segment
@@ -1007,7 +1061,7 @@ parameter with the
- #pragma code-name ("MyCODE")
+ #pragma code-name ("MyCODE")
@@ -1035,10 +1089,21 @@ parameter with the
- #pragma data-name ("MyDATA")
+ #pragma data-name ("MyDATA")
+#pragma inline-stdfuncs ([push,] on|off)
+
+ Allow the compiler to inline some standard functions from the C library like
+ strlen. If the argument is "off", inlining is disabled, otherwise it is enabled.
+
+ See also the the #pragma local-strings ([push,] on|off)
When "on", emit string literals to the data segment when they're encountered
@@ -1083,7 +1148,7 @@ parameter with the
- #pragma rodata-name ("MyRODATA")
+ #pragma rodata-name ("MyRODATA")
@@ -1105,9 +1170,9 @@ parameter with the
- #pragma regvaraddr(on) /* Allow taking the address
- * of register variables
- */
+ #pragma regvaraddr(on) /* Allow taking the address
+ * of register variables
+ */
@@ -1154,7 +1219,7 @@ parameter with the
/* Don't warn about the unused parameter in function func */
- #pragma warn (unused-param, push, off)
+ #pragma warn (unused-param, push, off)
static int func (int unused)
{
return 0;
@@ -1187,13 +1252,12 @@ parameter with the
- extern int foo;
- #pragma zpsym ("foo"); /* foo is in the zeropage */
+ extern int foo;
+ #pragma zpsym ("foo"); /* foo is in the zeropage */
-
Register variables
The runtime for all supported platforms has 6 bytes of zero page space
@@ -1450,14 +1514,14 @@ including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
-- 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.
-
- Altered source versions must be plainly marked as such, and must not
- be misrepresented as being the original software.
-
- This notice may not be removed or altered from any source
- distribution.
+
- 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.
+
- Altered source versions must be plainly marked as such, and must not
+ be misrepresented as being the original software.
+
- This notice may not be removed or altered from any source
+ distribution.
diff --git a/doc/cl65.sgml b/doc/cl65.sgml
index eef6a12a3..ffeba2321 100644
--- a/doc/cl65.sgml
+++ b/doc/cl65.sgml
@@ -54,9 +54,9 @@ Short options:
-L path Specify a library search path
-Ln name Create a VICE label file
-O Optimize code
- -Oi Optimize code, inline functions
+ -Oi Optimize code, inline more code
-Or Optimize code, honour the register keyword
- -Os Optimize code, inline known C funtions
+ -Os Optimize code, inline standard funtions
-S Compile but don't assemble and link
-T Include source as comment
-V Print the version number
diff --git a/include/ctype.h b/include/ctype.h
index b440bfb70..17cbafe9f 100644
--- a/include/ctype.h
+++ b/include/ctype.h
@@ -89,9 +89,9 @@ unsigned char __fastcall__ toascii (unsigned char c);
** #undef'ing the macroes.
** Please note that the following macroes do NOT handle EOF correctly, as
** stated in the manual. If you need correct behaviour for EOF, don't
-** use -Os, or #undefine the following macroes.
+** use --eagerly-inline-funcs, or #undefine the following macroes.
*/
-#ifdef __OPT_s__
+#ifdef __EAGERLY_INLINE_FUNCS__
#define isalnum(c) (__AX__ = (c), \
__asm__ ("tay"), \
diff --git a/src/cc65/compile.c b/src/cc65/compile.c
index 4425b6aad..3c1042154 100644
--- a/src/cc65/compile.c
+++ b/src/cc65/compile.c
@@ -335,17 +335,22 @@ void Compile (const char* FileName)
** changes using #pragma later.
*/
if (IS_Get (&Optimize)) {
- long CodeSize = IS_Get (&CodeSizeFactor);
DefineNumericMacro ("__OPT__", 1);
+ }
+ {
+ long CodeSize = IS_Get (&CodeSizeFactor);
if (CodeSize > 100) {
DefineNumericMacro ("__OPT_i__", CodeSize);
}
- if (IS_Get (&EnableRegVars)) {
- DefineNumericMacro ("__OPT_r__", 1);
- }
- if (IS_Get (&InlineStdFuncs)) {
- DefineNumericMacro ("__OPT_s__", 1);
- }
+ }
+ if (IS_Get (&EnableRegVars)) {
+ DefineNumericMacro ("__OPT_r__", 1);
+ }
+ if (IS_Get (&InlineStdFuncs)) {
+ DefineNumericMacro ("__OPT_s__", 1);
+ }
+ if (IS_Get (&EagerlyInlineFuncs)) {
+ DefineNumericMacro ("__EAGERLY_INLINE_FUNCS__", 1);
}
/* __TIME__ and __DATE__ macros */
diff --git a/src/cc65/global.c b/src/cc65/global.c
index dbdd72f3c..a337549fe 100644
--- a/src/cc65/global.c
+++ b/src/cc65/global.c
@@ -53,7 +53,8 @@ unsigned RegisterSpace = 6; /* Space available for register vars */
/* Stackable options */
IntStack WritableStrings = INTSTACK(0); /* Literal strings are r/w */
IntStack LocalStrings = INTSTACK(0); /* Emit string literals immediately */
-IntStack InlineStdFuncs = INTSTACK(0); /* Inline some known functions */
+IntStack InlineStdFuncs = INTSTACK(0); /* Inline some standard functions */
+IntStack EagerlyInlineFuncs = INTSTACK(0); /* Eagerly inline some known functions */
IntStack EnableRegVars = INTSTACK(0); /* Enable register variables */
IntStack AllowRegVarAddr = INTSTACK(0); /* Allow taking addresses of register vars */
IntStack RegVarsToCallStack = INTSTACK(0); /* Save reg variables on call stack */
diff --git a/src/cc65/global.h b/src/cc65/global.h
index 8b0af5a83..4ffc84a39 100644
--- a/src/cc65/global.h
+++ b/src/cc65/global.h
@@ -61,7 +61,8 @@ extern unsigned RegisterSpace; /* Space available for register
/* Stackable options */
extern IntStack WritableStrings; /* Literal strings are r/w */
extern IntStack LocalStrings; /* Emit string literals immediately */
-extern IntStack InlineStdFuncs; /* Inline some known functions */
+extern IntStack InlineStdFuncs; /* Inline some standard functions */
+extern IntStack EagerlyInlineFuncs; /* Eagerly inline some known functions */
extern IntStack EnableRegVars; /* Enable register variables */
extern IntStack AllowRegVarAddr; /* Allow taking addresses of register vars */
extern IntStack RegVarsToCallStack; /* Save reg variables on call stack */
diff --git a/src/cc65/main.c b/src/cc65/main.c
index 9ed19b90c..d3d298876 100644
--- a/src/cc65/main.c
+++ b/src/cc65/main.c
@@ -88,7 +88,7 @@ static void Usage (void)
" -O\t\t\t\tOptimize code\n"
" -Oi\t\t\t\tOptimize code, inline more code\n"
" -Or\t\t\t\tEnable register variables\n"
- " -Os\t\t\t\tInline some known functions\n"
+ " -Os\t\t\t\tInline some standard functions\n"
" -T\t\t\t\tInclude source as comment\n"
" -V\t\t\t\tPrint the compiler version number\n"
" -W warning[,...]\t\tSuppress warnings\n"
@@ -118,9 +118,11 @@ static void Usage (void)
" --debug-opt name\t\tDebug optimization steps\n"
" --dep-target target\t\tUse this dependency target\n"
" --disable-opt name\t\tDisable an optimization step\n"
+ " --eagerly-inline-funcs\t\tEagerly inline some known functions\n"
" --enable-opt name\t\tEnable an optimization step\n"
" --help\t\t\tHelp (this text)\n"
" --include-dir dir\t\tSet an include directory search path\n"
+ " --inline-stdfuncs\t\tInline some standard functions\n"
" --list-opt-steps\t\tList all optimizer steps and exit\n"
" --list-warnings\t\tList available warning types for -W\n"
" --local-strings\t\tEmit string literals immediately\n"
@@ -581,6 +583,16 @@ static void OptDisableOpt (const char* Opt attribute ((unused)), const char* Arg
+static void OptEagerlyInlineFuncs (const char* Opt attribute((unused)),
+ const char* Arg attribute((unused)))
+/* Eagerly inline some known functions */
+{
+ IS_Set (&InlineStdFuncs, 1);
+ IS_Set (&EagerlyInlineFuncs, 1);
+}
+
+
+
static void OptEnableOpt (const char* Opt attribute ((unused)), const char* Arg)
/* Enable an optimization step */
{
@@ -608,6 +620,15 @@ static void OptIncludeDir (const char* Opt attribute ((unused)), const char* Arg
+static void OptInlineStdFuncs (const char* Opt attribute((unused)),
+ const char* Arg attribute((unused)))
+/* Inline some standard functions */
+{
+ IS_Set (&InlineStdFuncs, 1);
+}
+
+
+
static void OptListOptSteps (const char* Opt attribute ((unused)),
const char* Arg attribute ((unused)))
/* List all optimizer steps */
@@ -819,39 +840,41 @@ int main (int argc, char* argv[])
{
/* Program long options */
static const LongOpt OptTab[] = {
- { "--add-source", 0, OptAddSource },
- { "--all-cdecl", 0, OptAllCDecl },
- { "--bss-name", 1, OptBssName },
- { "--check-stack", 0, OptCheckStack },
- { "--code-name", 1, OptCodeName },
- { "--codesize", 1, OptCodeSize },
- { "--cpu", 1, OptCPU },
- { "--create-dep", 1, OptCreateDep },
- { "--create-full-dep", 1, OptCreateFullDep },
- { "--data-name", 1, OptDataName },
- { "--debug", 0, OptDebug },
- { "--debug-info", 0, OptDebugInfo },
- { "--debug-opt", 1, OptDebugOpt },
- { "--debug-opt-output", 0, OptDebugOptOutput },
- { "--dep-target", 1, OptDepTarget },
- { "--disable-opt", 1, OptDisableOpt },
- { "--enable-opt", 1, OptEnableOpt },
- { "--help", 0, OptHelp },
- { "--include-dir", 1, OptIncludeDir },
- { "--list-opt-steps", 0, OptListOptSteps },
- { "--list-warnings", 0, OptListWarnings },
- { "--local-strings", 0, OptLocalStrings },
- { "--memory-model", 1, OptMemoryModel },
- { "--register-space", 1, OptRegisterSpace },
- { "--register-vars", 0, OptRegisterVars },
- { "--rodata-name", 1, OptRodataName },
- { "--signed-chars", 0, OptSignedChars },
- { "--standard", 1, OptStandard },
- { "--static-locals", 0, OptStaticLocals },
- { "--target", 1, OptTarget },
- { "--verbose", 0, OptVerbose },
- { "--version", 0, OptVersion },
- { "--writable-strings", 0, OptWritableStrings },
+ { "--add-source", 0, OptAddSource },
+ { "--all-cdecl", 0, OptAllCDecl },
+ { "--bss-name", 1, OptBssName },
+ { "--check-stack", 0, OptCheckStack },
+ { "--code-name", 1, OptCodeName },
+ { "--codesize", 1, OptCodeSize },
+ { "--cpu", 1, OptCPU },
+ { "--create-dep", 1, OptCreateDep },
+ { "--create-full-dep", 1, OptCreateFullDep },
+ { "--data-name", 1, OptDataName },
+ { "--debug", 0, OptDebug },
+ { "--debug-info", 0, OptDebugInfo },
+ { "--debug-opt", 1, OptDebugOpt },
+ { "--debug-opt-output", 0, OptDebugOptOutput },
+ { "--dep-target", 1, OptDepTarget },
+ { "--disable-opt", 1, OptDisableOpt },
+ { "--eagerly-inline-funcs", 0, OptEagerlyInlineFuncs },
+ { "--enable-opt", 1, OptEnableOpt },
+ { "--help", 0, OptHelp },
+ { "--include-dir", 1, OptIncludeDir },
+ { "--inline-stdfuncs", 0, OptInlineStdFuncs },
+ { "--list-opt-steps", 0, OptListOptSteps },
+ { "--list-warnings", 0, OptListWarnings },
+ { "--local-strings", 0, OptLocalStrings },
+ { "--memory-model", 1, OptMemoryModel },
+ { "--register-space", 1, OptRegisterSpace },
+ { "--register-vars", 0, OptRegisterVars },
+ { "--rodata-name", 1, OptRodataName },
+ { "--signed-chars", 0, OptSignedChars },
+ { "--standard", 1, OptStandard },
+ { "--static-locals", 0, OptStaticLocals },
+ { "--target", 1, OptTarget },
+ { "--verbose", 0, OptVerbose },
+ { "--version", 0, OptVersion },
+ { "--writable-strings", 0, OptWritableStrings },
};
unsigned I;
diff --git a/src/cc65/pragma.c b/src/cc65/pragma.c
index 86739ce22..707546e1d 100644
--- a/src/cc65/pragma.c
+++ b/src/cc65/pragma.c
@@ -64,6 +64,7 @@
typedef enum {
PRAGMA_ILLEGAL = -1,
PRAGMA_ALIGN,
+ PRAGMA_ALLOW_EAGER_INLINE,
PRAGMA_BSS_NAME,
PRAGMA_BSSSEG, /* obsolete */
PRAGMA_CHARMAP,
@@ -74,6 +75,7 @@ typedef enum {
PRAGMA_CODESIZE,
PRAGMA_DATA_NAME,
PRAGMA_DATASEG, /* obsolete */
+ PRAGMA_INLINE_STDFUNCS,
PRAGMA_LOCAL_STRINGS,
PRAGMA_OPTIMIZE,
PRAGMA_REGVARADDR,
@@ -96,31 +98,33 @@ static const struct Pragma {
const char* Key; /* Keyword */
pragma_t Tok; /* Token */
} Pragmas[PRAGMA_COUNT] = {
- { "align", PRAGMA_ALIGN },
- { "bss-name", PRAGMA_BSS_NAME },
- { "bssseg", PRAGMA_BSSSEG }, /* obsolete */
- { "charmap", PRAGMA_CHARMAP },
- { "check-stack", PRAGMA_CHECK_STACK },
- { "checkstack", PRAGMA_CHECKSTACK }, /* obsolete */
- { "code-name", PRAGMA_CODE_NAME },
- { "codeseg", PRAGMA_CODESEG }, /* obsolete */
- { "codesize", PRAGMA_CODESIZE },
- { "data-name", PRAGMA_DATA_NAME },
- { "dataseg", PRAGMA_DATASEG }, /* obsolete */
- { "local-strings", PRAGMA_LOCAL_STRINGS },
- { "optimize", PRAGMA_OPTIMIZE },
- { "register-vars", PRAGMA_REGISTER_VARS },
- { "regvaraddr", PRAGMA_REGVARADDR },
- { "regvars", PRAGMA_REGVARS }, /* obsolete */
- { "rodata-name", PRAGMA_RODATA_NAME },
- { "rodataseg", PRAGMA_RODATASEG }, /* obsolete */
- { "signed-chars", PRAGMA_SIGNED_CHARS },
- { "signedchars", PRAGMA_SIGNEDCHARS }, /* obsolete */
- { "static-locals", PRAGMA_STATIC_LOCALS },
- { "staticlocals", PRAGMA_STATICLOCALS }, /* obsolete */
- { "warn", PRAGMA_WARN },
- { "writable-strings", PRAGMA_WRITABLE_STRINGS },
- { "zpsym", PRAGMA_ZPSYM },
+ { "align", PRAGMA_ALIGN },
+ { "allow-eager-inline", PRAGMA_ALLOW_EAGER_INLINE },
+ { "bss-name", PRAGMA_BSS_NAME },
+ { "bssseg", PRAGMA_BSSSEG }, /* obsolete */
+ { "charmap", PRAGMA_CHARMAP },
+ { "check-stack", PRAGMA_CHECK_STACK },
+ { "checkstack", PRAGMA_CHECKSTACK }, /* obsolete */
+ { "code-name", PRAGMA_CODE_NAME },
+ { "codeseg", PRAGMA_CODESEG }, /* obsolete */
+ { "codesize", PRAGMA_CODESIZE },
+ { "data-name", PRAGMA_DATA_NAME },
+ { "dataseg", PRAGMA_DATASEG }, /* obsolete */
+ { "inline-stdfuncs", PRAGMA_INLINE_STDFUNCS },
+ { "local-strings", PRAGMA_LOCAL_STRINGS },
+ { "optimize", PRAGMA_OPTIMIZE },
+ { "register-vars", PRAGMA_REGISTER_VARS },
+ { "regvaraddr", PRAGMA_REGVARADDR },
+ { "regvars", PRAGMA_REGVARS }, /* obsolete */
+ { "rodata-name", PRAGMA_RODATA_NAME },
+ { "rodataseg", PRAGMA_RODATASEG }, /* obsolete */
+ { "signed-chars", PRAGMA_SIGNED_CHARS },
+ { "signedchars", PRAGMA_SIGNEDCHARS }, /* obsolete */
+ { "static-locals", PRAGMA_STATIC_LOCALS },
+ { "staticlocals", PRAGMA_STATICLOCALS }, /* obsolete */
+ { "warn", PRAGMA_WARN },
+ { "writable-strings", PRAGMA_WRITABLE_STRINGS },
+ { "zpsym", PRAGMA_ZPSYM },
};
/* Result of ParsePushPop */
@@ -703,6 +707,10 @@ static void ParsePragma (void)
IntPragma (&B, &DataAlignment, 1, 4096);
break;
+ case PRAGMA_ALLOW_EAGER_INLINE:
+ FlagPragma (&B, &EagerlyInlineFuncs);
+ break;
+
case PRAGMA_BSSSEG:
Warning ("#pragma bssseg is obsolete, please use #pragma bss-name instead");
/* FALLTHROUGH */
@@ -739,6 +747,10 @@ static void ParsePragma (void)
SegNamePragma (&B, SEG_DATA);
break;
+ case PRAGMA_INLINE_STDFUNCS:
+ FlagPragma (&B, &InlineStdFuncs);
+ break;
+
case PRAGMA_LOCAL_STRINGS:
FlagPragma (&B, &LocalStrings);
break;
diff --git a/src/cc65/stdfunc.c b/src/cc65/stdfunc.c
index 720e6db15..7a0450146 100644
--- a/src/cc65/stdfunc.c
+++ b/src/cc65/stdfunc.c
@@ -261,262 +261,277 @@ static void StdFunc_memcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
goto ExitPoint;
}
- /* We've generated the complete code for the function now and know the
- ** types of all parameters. Check for situations where better code can
- ** be generated. If such a situation is detected, throw away the
- ** generated, and emit better code.
- */
- if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
- ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
- (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
- ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
- (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) {
+ if (IS_Get (&InlineStdFuncs)) {
- int Reg1 = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr);
- int Reg2 = ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr);
+ /* We've generated the complete code for the function now and know the
+ ** types of all parameters. Check for situations where better code can
+ ** be generated. If such a situation is detected, throw away the
+ ** generated, and emit better code.
+ */
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
+ (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
+ ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
+ (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) {
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ int Reg1 = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr);
+ int Reg2 = ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr);
- /* We need a label */
- Label = GetLocalLabel ();
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- /* Generate memcpy code */
- if (Arg3.Expr.IVal <= 127) {
+ /* We need a label */
+ Label = GetLocalLabel ();
- AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
- g_defcodelabel (Label);
- if (Reg2) {
- AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg2.Expr, 0));
- } else {
- AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, 0));
- }
- if (Reg1) {
- AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
- } else {
- AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
- }
- AddCodeLine ("dey");
- AddCodeLine ("bpl %s", LocalLabelName (Label));
+ /* Generate memcpy code */
+ if (Arg3.Expr.IVal <= 127) {
- } else {
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
+ g_defcodelabel (Label);
+ if (Reg2) {
+ AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg2.Expr, 0));
+ } else {
+ AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, 0));
+ }
+ if (Reg1) {
+ AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
+ } else {
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
+ }
+ AddCodeLine ("dey");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
- AddCodeLine ("ldy #$00");
- g_defcodelabel (Label);
- if (Reg2) {
- AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg2.Expr, 0));
- } else {
- AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, 0));
- }
- if (Reg1) {
- AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
} else {
- AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
- }
- AddCodeLine ("iny");
- AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
- AddCodeLine ("bne %s", LocalLabelName (Label));
- }
+ AddCodeLine ("ldy #$00");
+ g_defcodelabel (Label);
+ if (Reg2) {
+ AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg2.Expr, 0));
+ } else {
+ AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, 0));
+ }
+ if (Reg1) {
+ AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
+ } else {
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
+ }
+ AddCodeLine ("iny");
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
- /* memcpy returns the address, so the result is actually identical
- ** to the first argument.
- */
- *Expr = Arg1.Expr;
+ }
- } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
- ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) &&
- ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
- (Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) {
-
- /* It is possible to just use one index register even if the stack
- ** offset is not zero, by adjusting the offset to the constant
- ** address accordingly. But we cannot do this if the data in
- ** question is in the register space or at an absolute address less
- ** than 256. Register space is zero page, which means that the
- ** address calculation could overflow in the linker.
- */
- int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) &&
- !(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256);
+ /* memcpy returns the address, so the result is actually identical
+ ** to the first argument.
+ */
+ *Expr = Arg1.Expr;
- /* Calculate the real stack offset */
- Offs = ED_GetStackOffs (&Arg1.Expr, 0);
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) &&
+ ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
+ (Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) {
+
+ /* It is possible to just use one index register even if the stack
+ ** offset is not zero, by adjusting the offset to the constant
+ ** address accordingly. But we cannot do this if the data in
+ ** question is in the register space or at an absolute address less
+ ** than 256. Register space is zero page, which means that the
+ ** address calculation could overflow in the linker.
+ */
+ int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) &&
+ !(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256);
- /* We need a label */
- Label = GetLocalLabel ();
+ /* Calculate the real stack offset */
+ Offs = ED_GetStackOffs (&Arg1.Expr, 0);
- /* Generate memcpy code */
- if (Arg3.Expr.IVal <= 127 && !AllowOneIndex) {
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
+
+ /* We need a label */
+ Label = GetLocalLabel ();
+
+ /* Generate memcpy code */
+ if (Arg3.Expr.IVal <= 127 && !AllowOneIndex) {
+
+ if (Offs == 0) {
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1));
+ g_defcodelabel (Label);
+ AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
+ AddCodeLine ("sta (sp),y");
+ AddCodeLine ("dey");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
+ } else {
+ AddCodeLine ("ldx #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1));
+ g_defcodelabel (Label);
+ AddCodeLine ("lda %s,x", ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine ("sta (sp),y");
+ AddCodeLine ("dey");
+ AddCodeLine ("dex");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
+ }
- if (Offs == 0) {
- AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1));
- g_defcodelabel (Label);
- AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
- AddCodeLine ("sta (sp),y");
- AddCodeLine ("dey");
- AddCodeLine ("bpl %s", LocalLabelName (Label));
} else {
- AddCodeLine ("ldx #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
- AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1));
- g_defcodelabel (Label);
- AddCodeLine ("lda %s,x", ED_GetLabelName (&Arg2.Expr, 0));
- AddCodeLine ("sta (sp),y");
- AddCodeLine ("dey");
- AddCodeLine ("dex");
- AddCodeLine ("bpl %s", LocalLabelName (Label));
- }
- } else {
+ if (Offs == 0 || AllowOneIndex) {
+ AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
+ g_defcodelabel (Label);
+ AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
+ AddCodeLine ("sta (sp),y");
+ AddCodeLine ("iny");
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
+ } else {
+ AddCodeLine ("ldx #$00");
+ AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
+ g_defcodelabel (Label);
+ AddCodeLine ("lda %s,x", ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine ("sta (sp),y");
+ AddCodeLine ("iny");
+ AddCodeLine ("inx");
+ AddCmpCodeIfSizeNot256 ("cpx #$%02X", Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
+ }
- if (Offs == 0 || AllowOneIndex) {
- AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
- g_defcodelabel (Label);
- AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
- AddCodeLine ("sta (sp),y");
- AddCodeLine ("iny");
- AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal);
- AddCodeLine ("bne %s", LocalLabelName (Label));
- } else {
- AddCodeLine ("ldx #$00");
- AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
- g_defcodelabel (Label);
- AddCodeLine ("lda %s,x", ED_GetLabelName (&Arg2.Expr, 0));
- AddCodeLine ("sta (sp),y");
- AddCodeLine ("iny");
- AddCodeLine ("inx");
- AddCmpCodeIfSizeNot256 ("cpx #$%02X", Arg3.Expr.IVal);
- AddCodeLine ("bne %s", LocalLabelName (Label));
}
+ /* memcpy returns the address, so the result is actually identical
+ ** to the first argument.
+ */
+ *Expr = Arg1.Expr;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
}
- /* memcpy returns the address, so the result is actually identical
- ** to the first argument.
- */
- *Expr = Arg1.Expr;
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
+ (Arg2.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256 &&
+ ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) {
+
+ /* It is possible to just use one index register even if the stack
+ ** offset is not zero, by adjusting the offset to the constant
+ ** address accordingly. But we cannot do this if the data in
+ ** question is in the register space or at an absolute address less
+ ** than 256. Register space is zero page, which means that the
+ ** address calculation could overflow in the linker.
+ */
+ int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) &&
+ !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
- } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
- ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
- (Arg2.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256 &&
- ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) {
-
- /* It is possible to just use one index register even if the stack
- ** offset is not zero, by adjusting the offset to the constant
- ** address accordingly. But we cannot do this if the data in
- ** question is in the register space or at an absolute address less
- ** than 256. Register space is zero page, which means that the
- ** address calculation could overflow in the linker.
- */
- int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) &&
- !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
+ /* Calculate the real stack offset */
+ Offs = ED_GetStackOffs (&Arg2.Expr, 0);
+
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
+
+ /* We need a label */
+ Label = GetLocalLabel ();
+
+ /* Generate memcpy code */
+ if (Arg3.Expr.IVal <= 127 && !AllowOneIndex) {
+
+ if (Offs == 0) {
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal - 1));
+ g_defcodelabel (Label);
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
+ AddCodeLine ("dey");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
+ } else {
+ AddCodeLine ("ldx #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1));
+ g_defcodelabel (Label);
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0));
+ AddCodeLine ("dey");
+ AddCodeLine ("dex");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
+ }
+
+ } else {
+
+ if (Offs == 0 || AllowOneIndex) {
+ AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
+ g_defcodelabel (Label);
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, -Offs));
+ AddCodeLine ("iny");
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
+ } else {
+ AddCodeLine ("ldx #$00");
+ AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
+ g_defcodelabel (Label);
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0));
+ AddCodeLine ("iny");
+ AddCodeLine ("inx");
+ AddCmpCodeIfSizeNot256 ("cpx #$%02X", Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
+ }
- /* Calculate the real stack offset */
- Offs = ED_GetStackOffs (&Arg2.Expr, 0);
+ }
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ /* memcpy returns the address, so the result is actually identical
+ ** to the first argument.
+ */
+ *Expr = Arg1.Expr;
- /* We need a label */
- Label = GetLocalLabel ();
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
- /* Generate memcpy code */
- if (Arg3.Expr.IVal <= 127 && !AllowOneIndex) {
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
+ (Offs = ED_GetStackOffs (&Arg2.Expr, 0)) == 0) {
- if (Offs == 0) {
+ /* Drop the generated code but leave the load of the first argument*/
+ RemoveCode (&Arg1.Push);
+
+ /* We need a label */
+ Label = GetLocalLabel ();
+
+ /* Generate memcpy code */
+ AddCodeLine ("sta ptr1");
+ AddCodeLine ("stx ptr1+1");
+ if (Arg3.Expr.IVal <= 127) {
AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal - 1));
g_defcodelabel (Label);
AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
+ AddCodeLine ("sta (ptr1),y");
AddCodeLine ("dey");
AddCodeLine ("bpl %s", LocalLabelName (Label));
} else {
- AddCodeLine ("ldx #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
- AddCodeLine ("ldy #$%02X", (unsigned char) (Offs + Arg3.Expr.IVal - 1));
+ AddCodeLine ("ldy #$00");
g_defcodelabel (Label);
AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0));
- AddCodeLine ("dey");
- AddCodeLine ("dex");
- AddCodeLine ("bpl %s", LocalLabelName (Label));
- }
-
- } else {
-
- if (Offs == 0 || AllowOneIndex) {
- AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
- g_defcodelabel (Label);
- AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, -Offs));
+ AddCodeLine ("sta (ptr1),y");
AddCodeLine ("iny");
- AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal);
- AddCodeLine ("bne %s", LocalLabelName (Label));
- } else {
- AddCodeLine ("ldx #$00");
- AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
- g_defcodelabel (Label);
- AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0));
- AddCodeLine ("iny");
- AddCodeLine ("inx");
- AddCmpCodeIfSizeNot256 ("cpx #$%02X", Arg3.Expr.IVal);
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
}
- }
+ /* Reload result - X hasn't changed by the code above */
+ AddCodeLine ("lda ptr1");
- /* memcpy returns the address, so the result is actually identical
- ** to the first argument.
- */
- *Expr = Arg1.Expr;
-
- } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
- ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
- (Offs = ED_GetStackOffs (&Arg2.Expr, 0)) == 0) {
-
- /* Drop the generated code but leave the load of the first argument*/
- RemoveCode (&Arg1.Push);
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
- /* We need a label */
- Label = GetLocalLabel ();
-
- /* Generate memcpy code */
- AddCodeLine ("sta ptr1");
- AddCodeLine ("stx ptr1+1");
- if (Arg3.Expr.IVal <= 127) {
- AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal - 1));
- g_defcodelabel (Label);
- AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta (ptr1),y");
- AddCodeLine ("dey");
- AddCodeLine ("bpl %s", LocalLabelName (Label));
- } else {
- AddCodeLine ("ldy #$00");
- g_defcodelabel (Label);
- AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta (ptr1),y");
- AddCodeLine ("iny");
- AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
- AddCodeLine ("bne %s", LocalLabelName (Label));
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
}
-
- /* Reload result - X hasn't changed by the code above */
- AddCodeLine ("lda ptr1");
-
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = GetFuncReturn (Expr->Type);
-
- } else {
-
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = GetFuncReturn (Expr->Type);
-
}
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
+
ExitPoint:
/* We expect the closing brace */
ConsumeRParen ();
@@ -595,140 +610,151 @@ static void StdFunc_memset (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
goto ExitPoint;
}
- /* We've generated the complete code for the function now and know the
- ** types of all parameters. Check for situations where better code can
- ** be generated. If such a situation is detected, throw away the
- ** generated, and emit better code.
- ** Note: Lots of improvements would be possible here, but I will
- ** concentrate on the most common case: memset with arguments 2 and 3
- ** being constant numerical values. Some checks have shown that this
- ** covers nearly 90% of all memset calls.
- */
- if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
- ED_IsConstAbsInt (&Arg2.Expr) &&
- ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
- (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) {
+ if (IS_Get (&InlineStdFuncs)) {
- int Reg = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr);
+ /* We've generated the complete code for the function now and know the
+ ** types of all parameters. Check for situations where better code can
+ ** be generated. If such a situation is detected, throw away the
+ ** generated, and emit better code.
+ ** Note: Lots of improvements would be possible here, but I will
+ ** concentrate on the most common case: memset with arguments 2 and 3
+ ** being constant numerical values. Some checks have shown that this
+ ** covers nearly 90% of all memset calls.
+ */
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ED_IsConstAbsInt (&Arg2.Expr) &&
+ ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
+ (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)))) {
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ int Reg = ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr);
- /* We need a label */
- Label = GetLocalLabel ();
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- /* Generate memset code */
- if (Arg3.Expr.IVal <= 127) {
+ /* We need a label */
+ Label = GetLocalLabel ();
- AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
- AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
- g_defcodelabel (Label);
- if (Reg) {
- AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
- } else {
- AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
- }
- AddCodeLine ("dey");
- AddCodeLine ("bpl %s", LocalLabelName (Label));
+ /* Generate memset code */
+ if (Arg3.Expr.IVal <= 127) {
- } else {
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
+ AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
+ g_defcodelabel (Label);
+ if (Reg) {
+ AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
+ } else {
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
+ }
+ AddCodeLine ("dey");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
- AddCodeLine ("ldy #$00");
- AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
- g_defcodelabel (Label);
- if (Reg) {
- AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
} else {
- AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
- }
- AddCodeLine ("iny");
- AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
- AddCodeLine ("bne %s", LocalLabelName (Label));
- }
-
- /* memset returns the address, so the result is actually identical
- ** to the first argument.
- */
- *Expr = Arg1.Expr;
-
- } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
- ED_IsConstAbsInt (&Arg2.Expr) &&
- ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
- (Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) {
-
- /* Calculate the real stack offset */
- int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
+ AddCodeLine ("ldy #$00");
+ AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
+ g_defcodelabel (Label);
+ if (Reg) {
+ AddCodeLine ("sta (%s),y", ED_GetLabelName (&Arg1.Expr, 0));
+ } else {
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, 0));
+ }
+ AddCodeLine ("iny");
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ }
- /* We need a label */
- Label = GetLocalLabel ();
+ /* memset returns the address, so the result is actually identical
+ ** to the first argument.
+ */
+ *Expr = Arg1.Expr;
- /* Generate memset code */
- AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
- AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
- g_defcodelabel (Label);
- AddCodeLine ("sta (sp),y");
- AddCodeLine ("iny");
- AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal);
- AddCodeLine ("bne %s", LocalLabelName (Label));
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
- /* memset returns the address, so the result is actually identical
- ** to the first argument.
- */
- *Expr = Arg1.Expr;
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ED_IsConstAbsInt (&Arg2.Expr) &&
+ ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
+ (Arg1.Expr.IVal - StackPtr) + Arg3.Expr.IVal < 256) {
- } else if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
- ED_IsConstAbsInt (&Arg2.Expr) &&
- (Arg2.Expr.IVal != 0 || IS_Get (&CodeSizeFactor) > 200)) {
+ /* Calculate the real stack offset */
+ int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
- /* Remove all of the generated code but the load of the first
- ** argument.
- */
- RemoveCode (&Arg1.Push);
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- /* We need a label */
- Label = GetLocalLabel ();
+ /* We need a label */
+ Label = GetLocalLabel ();
- /* Generate code */
- AddCodeLine ("sta ptr1");
- AddCodeLine ("stx ptr1+1");
- if (Arg3.Expr.IVal <= 127) {
- AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
+ /* Generate memset code */
+ AddCodeLine ("ldy #$%02X", (unsigned char) Offs);
AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
g_defcodelabel (Label);
- AddCodeLine ("sta (ptr1),y");
- AddCodeLine ("dey");
- AddCodeLine ("bpl %s", LocalLabelName (Label));
- } else {
- AddCodeLine ("ldy #$00");
- AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
- g_defcodelabel (Label);
- AddCodeLine ("sta (ptr1),y");
+ AddCodeLine ("sta (sp),y");
AddCodeLine ("iny");
- AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Offs + Arg3.Expr.IVal);
AddCodeLine ("bne %s", LocalLabelName (Label));
+
+ /* memset returns the address, so the result is actually identical
+ ** to the first argument.
+ */
+ *Expr = Arg1.Expr;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
}
- /* Load the function result pointer into a/x (x is still valid). This
- ** code will get removed by the optimizer if it is not used later.
- */
- AddCodeLine ("lda ptr1");
+ if (ED_IsConstAbsInt (&Arg3.Expr) && Arg3.Expr.IVal <= 256 &&
+ ED_IsConstAbsInt (&Arg2.Expr) &&
+ (Arg2.Expr.IVal != 0 || IS_Get (&CodeSizeFactor) > 200)) {
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = GetFuncReturn (Expr->Type);
+ /* Remove all of the generated code but the load of the first
+ ** argument.
+ */
+ RemoveCode (&Arg1.Push);
- } else {
+ /* We need a label */
+ Label = GetLocalLabel ();
+
+ /* Generate code */
+ AddCodeLine ("sta ptr1");
+ AddCodeLine ("stx ptr1+1");
+ if (Arg3.Expr.IVal <= 127) {
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Arg3.Expr.IVal-1));
+ AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
+ g_defcodelabel (Label);
+ AddCodeLine ("sta (ptr1),y");
+ AddCodeLine ("dey");
+ AddCodeLine ("bpl %s", LocalLabelName (Label));
+ } else {
+ AddCodeLine ("ldy #$00");
+ AddCodeLine ("lda #$%02X", (unsigned char) Arg2.Expr.IVal);
+ g_defcodelabel (Label);
+ AddCodeLine ("sta (ptr1),y");
+ AddCodeLine ("iny");
+ AddCmpCodeIfSizeNot256 ("cpy #$%02X", Arg3.Expr.IVal);
+ AddCodeLine ("bne %s", LocalLabelName (Label));
+ }
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = GetFuncReturn (Expr->Type);
+ /* Load the function result pointer into a/x (x is still valid). This
+ ** code will get removed by the optimizer if it is not used later.
+ */
+ AddCodeLine ("lda ptr1");
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
}
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
+
ExitPoint:
/* We expect the closing brace */
ConsumeRParen ();
@@ -790,142 +816,142 @@ static void StdFunc_strcmp (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
ECount1 = ECount2;
}
- /* If the second argument is the empty string literal, we can generate
- ** more efficient code.
- */
- if (ED_IsLocLiteral (&Arg2.Expr) &&
- IS_Get (&WritableStrings) == 0 &&
- GetLiteralSize (Arg2.Expr.LVal) == 1 &&
- GetLiteralStr (Arg2.Expr.LVal)[0] == '\0') {
+ if (IS_Get (&InlineStdFuncs)) {
- /* Drop the generated code so we have the first argument in the
- ** primary
+ /* If the second argument is the empty string literal, we can generate
+ ** more efficient code.
*/
- RemoveCode (&Arg1.Push);
+ if (ED_IsLocLiteral (&Arg2.Expr) &&
+ IS_Get (&WritableStrings) == 0 &&
+ GetLiteralSize (Arg2.Expr.LVal) == 1 &&
+ GetLiteralStr (Arg2.Expr.LVal)[0] == '\0') {
- /* We don't need the literal any longer */
- ReleaseLiteral (Arg2.Expr.LVal);
-
- /* We do now have Arg1 in the primary. Load the first character from
- ** this string and cast to int. This is the function result.
- */
- IsArray = IsTypeArray (Arg1.Type) && ED_IsRVal (&Arg1.Expr);
- if (IsArray && ED_IsLocStack (&Arg1.Expr) &&
- (Offs = ED_GetStackOffs (&Arg1.Expr, 0) < 256)) {
- /* Drop the generated code */
- RemoveCode (&Arg1.Load);
+ /* Drop the generated code so we have the first argument in the
+ ** primary
+ */
+ RemoveCode (&Arg1.Push);
- /* Generate code */
- AddCodeLine ("ldy #$%02X", Offs);
- AddCodeLine ("ldx #$00");
- AddCodeLine ("lda (sp),y");
- } else if (IsArray && ED_IsLocConst (&Arg1.Expr)) {
- /* Drop the generated code */
- RemoveCode (&Arg1.Load);
+ /* We don't need the literal any longer */
+ ReleaseLiteral (Arg2.Expr.LVal);
- /* Generate code */
- AddCodeLine ("ldx #$00");
- AddCodeLine ("lda %s", ED_GetLabelName (&Arg1.Expr, 0));
- } else {
- /* Drop part of the generated code so we have the first argument
- ** in the primary
+ /* We do now have Arg1 in the primary. Load the first character from
+ ** this string and cast to int. This is the function result.
*/
- RemoveCode (&Arg1.Push);
+ IsArray = IsTypeArray (Arg1.Type) && ED_IsRVal (&Arg1.Expr);
+ if (IsArray && ED_IsLocStack (&Arg1.Expr) &&
+ (Offs = ED_GetStackOffs (&Arg1.Expr, 0) < 256)) {
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Load);
+
+ /* Generate code */
+ AddCodeLine ("ldy #$%02X", Offs);
+ AddCodeLine ("ldx #$00");
+ AddCodeLine ("lda (sp),y");
+ } else if (IsArray && ED_IsLocConst (&Arg1.Expr)) {
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Load);
- /* Fetch the first char */
- g_getind (CF_CHAR | CF_UNSIGNED, 0);
- }
+ /* Generate code */
+ AddCodeLine ("ldx #$00");
+ AddCodeLine ("lda %s", ED_GetLabelName (&Arg1.Expr, 0));
+ } else {
+ /* Drop part of the generated code so we have the first argument
+ ** in the primary
+ */
+ RemoveCode (&Arg1.Push);
- } else if ((IS_Get (&CodeSizeFactor) >= 165) &&
- ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
- (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
- ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
- (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) &&
- (IS_Get (&InlineStdFuncs) || (ECount1 > 0 && ECount1 < 256))) {
+ /* Fetch the first char */
+ g_getind (CF_CHAR | CF_UNSIGNED, 0);
+ }
+ } else if ((IS_Get (&CodeSizeFactor) >= 165) &&
+ ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
+ (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
+ ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
+ (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) &&
+ (IS_Get (&EagerlyInlineFuncs) || (ECount1 > 0 && ECount1 < 256))) {
- unsigned Entry, Loop, Fin; /* Labels */
- const char* Load;
- const char* Compare;
+ unsigned Entry, Loop, Fin; /* Labels */
+ const char* Load;
+ const char* Compare;
- if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) {
- Load = "lda (%s),y";
- } else {
- Load = "lda %s,y";
- }
- if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
- Compare = "cmp (%s),y";
- } else {
- Compare = "cmp %s,y";
- }
+ if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) {
+ Load = "lda (%s),y";
+ } else {
+ Load = "lda %s,y";
+ }
+ if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
+ Compare = "cmp (%s),y";
+ } else {
+ Compare = "cmp %s,y";
+ }
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
-
- /* We need labels */
- Entry = GetLocalLabel ();
- Loop = GetLocalLabel ();
- Fin = GetLocalLabel ();
-
- /* Generate strcmp code */
- AddCodeLine ("ldy #$00");
- AddCodeLine ("beq %s", LocalLabelName (Entry));
- g_defcodelabel (Loop);
- AddCodeLine ("tax");
- AddCodeLine ("beq %s", LocalLabelName (Fin));
- AddCodeLine ("iny");
- g_defcodelabel (Entry);
- AddCodeLine (Load, ED_GetLabelName (&Arg1.Expr, 0));
- AddCodeLine (Compare, ED_GetLabelName (&Arg2.Expr, 0));
- AddCodeLine ("beq %s", LocalLabelName (Loop));
- AddCodeLine ("ldx #$01");
- AddCodeLine ("bcs %s", LocalLabelName (Fin));
- AddCodeLine ("ldx #$FF");
- g_defcodelabel (Fin);
-
- } else if ((IS_Get (&CodeSizeFactor) > 190) &&
- ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
- (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
- (IS_Get (&InlineStdFuncs) || (ECount1 > 0 && ECount1 < 256))) {
-
-
- unsigned Entry, Loop, Fin; /* Labels */
- const char* Compare;
-
- if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
- Compare = "cmp (%s),y";
- } else {
- Compare = "cmp %s,y";
- }
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- /* Drop the generated code */
- RemoveCode (&Arg1.Push);
+ /* We need labels */
+ Entry = GetLocalLabel ();
+ Loop = GetLocalLabel ();
+ Fin = GetLocalLabel ();
+
+ /* Generate strcmp code */
+ AddCodeLine ("ldy #$00");
+ AddCodeLine ("beq %s", LocalLabelName (Entry));
+ g_defcodelabel (Loop);
+ AddCodeLine ("tax");
+ AddCodeLine ("beq %s", LocalLabelName (Fin));
+ AddCodeLine ("iny");
+ g_defcodelabel (Entry);
+ AddCodeLine (Load, ED_GetLabelName (&Arg1.Expr, 0));
+ AddCodeLine (Compare, ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine ("beq %s", LocalLabelName (Loop));
+ AddCodeLine ("ldx #$01");
+ AddCodeLine ("bcs %s", LocalLabelName (Fin));
+ AddCodeLine ("ldx #$FF");
+ g_defcodelabel (Fin);
+
+ } else if ((IS_Get (&CodeSizeFactor) > 190) &&
+ ((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
+ (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
+ (IS_Get (&EagerlyInlineFuncs) || (ECount1 > 0 && ECount1 < 256))) {
- /* We need labels */
- Entry = GetLocalLabel ();
- Loop = GetLocalLabel ();
- Fin = GetLocalLabel ();
-
- /* Store Arg1 into ptr1 */
- AddCodeLine ("sta ptr1");
- AddCodeLine ("stx ptr1+1");
-
- /* Generate strcmp code */
- AddCodeLine ("ldy #$00");
- AddCodeLine ("beq %s", LocalLabelName (Entry));
- g_defcodelabel (Loop);
- AddCodeLine ("tax");
- AddCodeLine ("beq %s", LocalLabelName (Fin));
- AddCodeLine ("iny");
- g_defcodelabel (Entry);
- AddCodeLine ("lda (ptr1),y");
- AddCodeLine (Compare, ED_GetLabelName (&Arg2.Expr, 0));
- AddCodeLine ("beq %s", LocalLabelName (Loop));
- AddCodeLine ("ldx #$01");
- AddCodeLine ("bcs %s", LocalLabelName (Fin));
- AddCodeLine ("ldx #$FF");
- g_defcodelabel (Fin);
+ unsigned Entry, Loop, Fin; /* Labels */
+ const char* Compare;
+ if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
+ Compare = "cmp (%s),y";
+ } else {
+ Compare = "cmp %s,y";
+ }
+
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Push);
+
+ /* We need labels */
+ Entry = GetLocalLabel ();
+ Loop = GetLocalLabel ();
+ Fin = GetLocalLabel ();
+
+ /* Store Arg1 into ptr1 */
+ AddCodeLine ("sta ptr1");
+ AddCodeLine ("stx ptr1+1");
+
+ /* Generate strcmp code */
+ AddCodeLine ("ldy #$00");
+ AddCodeLine ("beq %s", LocalLabelName (Entry));
+ g_defcodelabel (Loop);
+ AddCodeLine ("tax");
+ AddCodeLine ("beq %s", LocalLabelName (Fin));
+ AddCodeLine ("iny");
+ g_defcodelabel (Entry);
+ AddCodeLine ("lda (ptr1),y");
+ AddCodeLine (Compare, ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine ("beq %s", LocalLabelName (Loop));
+ AddCodeLine ("ldx #$01");
+ AddCodeLine ("bcs %s", LocalLabelName (Fin));
+ AddCodeLine ("ldx #$FF");
+ g_defcodelabel (Fin);
+ }
}
/* The function result is an rvalue in the primary register */
@@ -983,142 +1009,154 @@ static void StdFunc_strcpy (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
/* Get the element count of argument 1 if it is an array */
ECount = ArrayElementCount (&Arg1);
- /* We've generated the complete code for the function now and know the
- ** types of all parameters. Check for situations where better code can
- ** be generated. If such a situation is detected, throw away the
- ** generated, and emit better code.
- */
- if (((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
- (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
- ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
- (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) &&
- (IS_Get (&InlineStdFuncs) ||
- (ECount != UNSPECIFIED && ECount < 256))) {
-
- const char* Load;
- const char* Store;
- if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
- Load = "lda (%s),y";
- } else {
- Load = "lda %s,y";
- }
- if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) {
- Store = "sta (%s),y";
- } else {
- Store = "sta %s,y";
- }
+ if (IS_Get (&InlineStdFuncs)) {
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ /* We've generated the complete code for the function now and know the
+ ** types of all parameters. Check for situations where better code can
+ ** be generated. If such a situation is detected, throw away the
+ ** generated, and emit better code.
+ */
+ if (((ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr)) ||
+ (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr))) &&
+ ((ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) ||
+ (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr))) &&
+ (IS_Get (&EagerlyInlineFuncs) ||
+ (ECount != UNSPECIFIED && ECount < 256))) {
+
+ const char* Load;
+ const char* Store;
+ if (ED_IsLVal (&Arg2.Expr) && ED_IsLocRegister (&Arg2.Expr)) {
+ Load = "lda (%s),y";
+ } else {
+ Load = "lda %s,y";
+ }
+ if (ED_IsLVal (&Arg1.Expr) && ED_IsLocRegister (&Arg1.Expr)) {
+ Store = "sta (%s),y";
+ } else {
+ Store = "sta %s,y";
+ }
- /* We need labels */
- L1 = GetLocalLabel ();
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- /* Generate strcpy code */
- AddCodeLine ("ldy #$FF");
- g_defcodelabel (L1);
- AddCodeLine ("iny");
- AddCodeLine (Load, ED_GetLabelName (&Arg2.Expr, 0));
- AddCodeLine (Store, ED_GetLabelName (&Arg1.Expr, 0));
- AddCodeLine ("bne %s", LocalLabelName (L1));
+ /* We need labels */
+ L1 = GetLocalLabel ();
- /* strcpy returns argument #1 */
- *Expr = Arg1.Expr;
+ /* Generate strcpy code */
+ AddCodeLine ("ldy #$FF");
+ g_defcodelabel (L1);
+ AddCodeLine ("iny");
+ AddCodeLine (Load, ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine (Store, ED_GetLabelName (&Arg1.Expr, 0));
+ AddCodeLine ("bne %s", LocalLabelName (L1));
- } else if (ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
- StackPtr >= -255 &&
- ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) {
+ /* strcpy returns argument #1 */
+ *Expr = Arg1.Expr;
- /* It is possible to just use one index register even if the stack
- ** offset is not zero, by adjusting the offset to the constant
- ** address accordingly. But we cannot do this if the data in
- ** question is in the register space or at an absolute address less
- ** than 256. Register space is zero page, which means that the
- ** address calculation could overflow in the linker.
- */
- int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) &&
- !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
- /* Calculate the real stack offset */
- int Offs = ED_GetStackOffs (&Arg2.Expr, 0);
+ if (ED_IsRVal (&Arg2.Expr) && ED_IsLocStack (&Arg2.Expr) &&
+ StackPtr >= -255 &&
+ ED_IsRVal (&Arg1.Expr) && ED_IsLocConst (&Arg1.Expr)) {
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ /* It is possible to just use one index register even if the stack
+ ** offset is not zero, by adjusting the offset to the constant
+ ** address accordingly. But we cannot do this if the data in
+ ** question is in the register space or at an absolute address less
+ ** than 256. Register space is zero page, which means that the
+ ** address calculation could overflow in the linker.
+ */
+ int AllowOneIndex = !ED_IsLocRegister (&Arg1.Expr) &&
+ !(ED_IsLocAbs (&Arg1.Expr) && Arg1.Expr.IVal < 256);
- /* We need labels */
- L1 = GetLocalLabel ();
+ /* Calculate the real stack offset */
+ int Offs = ED_GetStackOffs (&Arg2.Expr, 0);
- /* Generate strcpy code */
- AddCodeLine ("ldy #$%02X", (unsigned char) (Offs - 1));
- if (Offs == 0 || AllowOneIndex) {
- g_defcodelabel (L1);
- AddCodeLine ("iny");
- AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, -Offs));
- } else {
- AddCodeLine ("ldx #$FF");
- g_defcodelabel (L1);
- AddCodeLine ("iny");
- AddCodeLine ("inx");
- AddCodeLine ("lda (sp),y");
- AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0));
- }
- AddCodeLine ("bne %s", LocalLabelName (L1));
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- /* strcpy returns argument #1 */
- *Expr = Arg1.Expr;
+ /* We need labels */
+ L1 = GetLocalLabel ();
- } else if (ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) &&
- ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
- StackPtr >= -255) {
+ /* Generate strcpy code */
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Offs - 1));
+ if (Offs == 0 || AllowOneIndex) {
+ g_defcodelabel (L1);
+ AddCodeLine ("iny");
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("sta %s,y", ED_GetLabelName (&Arg1.Expr, -Offs));
+ } else {
+ AddCodeLine ("ldx #$FF");
+ g_defcodelabel (L1);
+ AddCodeLine ("iny");
+ AddCodeLine ("inx");
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("sta %s,x", ED_GetLabelName (&Arg1.Expr, 0));
+ }
+ AddCodeLine ("bne %s", LocalLabelName (L1));
- /* It is possible to just use one index register even if the stack
- ** offset is not zero, by adjusting the offset to the constant
- ** address accordingly. But we cannot do this if the data in
- ** question is in the register space or at an absolute address less
- ** than 256. Register space is zero page, which means that the
- ** address calculation could overflow in the linker.
- */
- int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) &&
- !(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256);
+ /* strcpy returns argument #1 */
+ *Expr = Arg1.Expr;
- /* Calculate the real stack offset */
- int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
- /* Drop the generated code */
- RemoveCode (&Arg1.Expr.Start);
+ if (ED_IsRVal (&Arg2.Expr) && ED_IsLocConst (&Arg2.Expr) &&
+ ED_IsRVal (&Arg1.Expr) && ED_IsLocStack (&Arg1.Expr) &&
+ StackPtr >= -255) {
- /* We need labels */
- L1 = GetLocalLabel ();
+ /* It is possible to just use one index register even if the stack
+ ** offset is not zero, by adjusting the offset to the constant
+ ** address accordingly. But we cannot do this if the data in
+ ** question is in the register space or at an absolute address less
+ ** than 256. Register space is zero page, which means that the
+ ** address calculation could overflow in the linker.
+ */
+ int AllowOneIndex = !ED_IsLocRegister (&Arg2.Expr) &&
+ !(ED_IsLocAbs (&Arg2.Expr) && Arg2.Expr.IVal < 256);
- /* Generate strcpy code */
- AddCodeLine ("ldy #$%02X", (unsigned char) (Offs - 1));
- if (Offs == 0 || AllowOneIndex) {
- g_defcodelabel (L1);
- AddCodeLine ("iny");
- AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
- AddCodeLine ("sta (sp),y");
- } else {
- AddCodeLine ("ldx #$FF");
- g_defcodelabel (L1);
- AddCodeLine ("iny");
- AddCodeLine ("inx");
- AddCodeLine ("lda %s,x", ED_GetLabelName (&Arg2.Expr, 0));
- AddCodeLine ("sta (sp),y");
- }
- AddCodeLine ("bne %s", LocalLabelName (L1));
+ /* Calculate the real stack offset */
+ int Offs = ED_GetStackOffs (&Arg1.Expr, 0);
- /* strcpy returns argument #1 */
- *Expr = Arg1.Expr;
+ /* Drop the generated code */
+ RemoveCode (&Arg1.Expr.Start);
- } else {
+ /* We need labels */
+ L1 = GetLocalLabel ();
+
+ /* Generate strcpy code */
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Offs - 1));
+ if (Offs == 0 || AllowOneIndex) {
+ g_defcodelabel (L1);
+ AddCodeLine ("iny");
+ AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg2.Expr, -Offs));
+ AddCodeLine ("sta (sp),y");
+ } else {
+ AddCodeLine ("ldx #$FF");
+ g_defcodelabel (L1);
+ AddCodeLine ("iny");
+ AddCodeLine ("inx");
+ AddCodeLine ("lda %s,x", ED_GetLabelName (&Arg2.Expr, 0));
+ AddCodeLine ("sta (sp),y");
+ }
+ AddCodeLine ("bne %s", LocalLabelName (L1));
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = GetFuncReturn (Expr->Type);
+ /* strcpy returns argument #1 */
+ *Expr = Arg1.Expr;
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
}
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = GetFuncReturn (Expr->Type);
+
+ExitPoint:
/* We expect the closing brace */
ConsumeRParen ();
}
@@ -1142,8 +1180,6 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
long ECount;
unsigned L;
-
-
/* Setup the argument type string */
ArgType[1].C = GetDefaultChar () | T_QUAL_CONST;
@@ -1175,125 +1211,148 @@ static void StdFunc_strlen (FuncDesc* F attribute ((unused)), ExprDesc* Expr)
/* Do type conversion */
TypeConversion (&Arg, ArgType);
- /* If the expression is a literal, and if string literals are read
- ** only, we can calculate the length of the string and remove it
- ** from the literal pool. Otherwise we have to calculate the length
- ** at runtime.
- */
- if (ED_IsLocLiteral (&Arg) && IS_Get (&WritableStrings) == 0) {
+ if (IS_Get (&Optimize)) {
- /* Constant string literal */
- ED_MakeConstAbs (Expr, GetLiteralSize (Arg.LVal) - 1, type_size_t);
+ /* If the expression is a literal, and if string literals are read
+ ** only, we can calculate the length of the string and remove it
+ ** from the literal pool. Otherwise we have to calculate the length
+ ** at runtime.
+ */
+ if (ED_IsLocLiteral (&Arg) && IS_Get (&WritableStrings) == 0) {
- /* We don't need the literal any longer */
- ReleaseLiteral (Arg.LVal);
+ /* Constant string literal */
+ ED_MakeConstAbs (Expr, GetLiteralSize (Arg.LVal) - 1, type_size_t);
- /* We will inline strlen for arrays with constant addresses, if either the
- ** inlining was forced on the command line, or the array is smaller than
- ** 256, so the inlining is considered safe.
- */
- } else if (ED_IsLocConst (&Arg) && IsArray &&
- (IS_Get (&InlineStdFuncs) || IsByteIndex)) {
-
- /* Generate the strlen code */
- L = GetLocalLabel ();
- AddCodeLine ("ldy #$FF");
- g_defcodelabel (L);
- AddCodeLine ("iny");
- AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg, 0));
- AddCodeLine ("bne %s", LocalLabelName (L));
- AddCodeLine ("tax");
- AddCodeLine ("tya");
-
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = type_size_t;
-
- /* We will inline strlen for arrays on the stack, if the array is
- ** completely within the reach of a byte sized index register.
- */
- } else if (ED_IsLocStack (&Arg) && IsArray && IsByteIndex &&
- (Arg.IVal - StackPtr) + ECount < 256) {
-
- /* Calculate the true stack offset */
- int Offs = ED_GetStackOffs (&Arg, 0);
-
- /* Generate the strlen code */
- L = GetLocalLabel ();
- AddCodeLine ("ldx #$FF");
- AddCodeLine ("ldy #$%02X", (unsigned char) (Offs-1));
- g_defcodelabel (L);
- AddCodeLine ("inx");
- AddCodeLine ("iny");
- AddCodeLine ("lda (sp),y");
- AddCodeLine ("bne %s", LocalLabelName (L));
- AddCodeLine ("txa");
- AddCodeLine ("ldx #$00");
-
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = type_size_t;
-
- /* strlen for a string that is pointed to by a register variable will only
- ** get inlined if requested on the command line, since we cannot know how
- ** big the buffer actually is, so inlining is not always safe.
- */
- } else if (ED_IsLocRegister (&Arg) && ED_IsLVal (&Arg) && IsPtr &&
- IS_Get (&InlineStdFuncs)) {
-
- /* Generate the strlen code */
- L = GetLocalLabel ();
- AddCodeLine ("ldy #$FF");
- g_defcodelabel (L);
- AddCodeLine ("iny");
- AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg, 0));
- AddCodeLine ("bne %s", LocalLabelName (L));
- AddCodeLine ("tax");
- AddCodeLine ("tya");
-
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = type_size_t;
-
- /* Last check: We will inline a generic strlen routine if inlining was
- ** requested on the command line, and the code size factor is more than
- ** 400 (code is 13 bytes vs. 3 for a jsr call).
- */
- } else if (IS_Get (&CodeSizeFactor) > 400 && IS_Get (&InlineStdFuncs)) {
-
- /* Load the expression into the primary */
- LoadExpr (CF_NONE, &Arg);
-
- /* Inline the function */
- L = GetLocalLabel ();
- AddCodeLine ("sta ptr1");
- AddCodeLine ("stx ptr1+1");
- AddCodeLine ("ldy #$FF");
- g_defcodelabel (L);
- AddCodeLine ("iny");
- AddCodeLine ("lda (ptr1),y");
- AddCodeLine ("bne %s", LocalLabelName (L));
- AddCodeLine ("tax");
- AddCodeLine ("tya");
-
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = type_size_t;
+ /* We don't need the literal any longer */
+ ReleaseLiteral (Arg.LVal);
- } else {
+ /* Bail out, no need for further improvements */
+ goto ExitPoint;
+ }
+ }
+
+ if (IS_Get (&InlineStdFuncs)) {
+
+ /* We will inline strlen for arrays with constant addresses, if either
+ ** requested on the command line, or the array is smaller than 256,
+ ** so the inlining is considered safe.
+ */
+ if (ED_IsLocConst (&Arg) && IsArray &&
+ (IS_Get (&EagerlyInlineFuncs) || IsByteIndex)) {
+
+ /* Generate the strlen code */
+ L = GetLocalLabel ();
+ AddCodeLine ("ldy #$FF");
+ g_defcodelabel (L);
+ AddCodeLine ("iny");
+ AddCodeLine ("lda %s,y", ED_GetLabelName (&Arg, 0));
+ AddCodeLine ("bne %s", LocalLabelName (L));
+ AddCodeLine ("tax");
+ AddCodeLine ("tya");
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = type_size_t;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
+
+ /* We will inline strlen for arrays on the stack, if the array is
+ ** completely within the reach of a byte sized index register.
+ */
+ if (ED_IsLocStack (&Arg) && IsArray && IsByteIndex &&
+ (Arg.IVal - StackPtr) + ECount < 256) {
+
+ /* Calculate the true stack offset */
+ int Offs = ED_GetStackOffs (&Arg, 0);
+
+ /* Generate the strlen code */
+ L = GetLocalLabel ();
+ AddCodeLine ("ldx #$FF");
+ AddCodeLine ("ldy #$%02X", (unsigned char) (Offs-1));
+ g_defcodelabel (L);
+ AddCodeLine ("inx");
+ AddCodeLine ("iny");
+ AddCodeLine ("lda (sp),y");
+ AddCodeLine ("bne %s", LocalLabelName (L));
+ AddCodeLine ("txa");
+ AddCodeLine ("ldx #$00");
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = type_size_t;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
- /* Load the expression into the primary */
- LoadExpr (CF_NONE, &Arg);
+ /* strlen for a string that is pointed to by a register variable will only
+ ** get inlined if requested on the command line, since we cannot know how
+ ** big the buffer actually is, so inlining is not always safe.
+ */
+ if (ED_IsLocRegister (&Arg) && ED_IsLVal (&Arg) && IsPtr &&
+ IS_Get (&EagerlyInlineFuncs)) {
- /* Call the strlen function */
- AddCodeLine ("jsr _%s", Func_strlen);
+ /* Generate the strlen code */
+ L = GetLocalLabel ();
+ AddCodeLine ("ldy #$FF");
+ g_defcodelabel (L);
+ AddCodeLine ("iny");
+ AddCodeLine ("lda (%s),y", ED_GetLabelName (&Arg, 0));
+ AddCodeLine ("bne %s", LocalLabelName (L));
+ AddCodeLine ("tax");
+ AddCodeLine ("tya");
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = type_size_t;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
+
+ /* Last check: We will inline a generic strlen routine if inlining was
+ ** requested on the command line, and the code size factor is more than
+ ** 400 (code is 13 bytes vs. 3 for a jsr call).
+ */
+ if (IS_Get (&CodeSizeFactor) > 400 && IS_Get (&EagerlyInlineFuncs)) {
- /* The function result is an rvalue in the primary register */
- ED_MakeRValExpr (Expr);
- Expr->Type = type_size_t;
+ /* Load the expression into the primary */
+ LoadExpr (CF_NONE, &Arg);
+ /* Inline the function */
+ L = GetLocalLabel ();
+ AddCodeLine ("sta ptr1");
+ AddCodeLine ("stx ptr1+1");
+ AddCodeLine ("ldy #$FF");
+ g_defcodelabel (L);
+ AddCodeLine ("iny");
+ AddCodeLine ("lda (ptr1),y");
+ AddCodeLine ("bne %s", LocalLabelName (L));
+ AddCodeLine ("tax");
+ AddCodeLine ("tya");
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = type_size_t;
+
+ /* Bail out, no need for further processing */
+ goto ExitPoint;
+ }
}
+ /* Load the expression into the primary */
+ LoadExpr (CF_NONE, &Arg);
+
+ /* Call the strlen function */
+ AddCodeLine ("jsr _%s", Func_strlen);
+
+ /* The function result is an rvalue in the primary register */
+ ED_MakeRValExpr (Expr);
+ Expr->Type = type_size_t;
+
+ExitPoint:
/* We expect the closing brace */
ConsumeRParen ();
}
--
2.39.5