#include "asmcode.h"
#include "asmlabel.h"
#include "check.h"
+#include "cpu.h"
#include "error.h"
#include "global.h"
#include "io.h"
AddCodeLine (".fopt\t\tcompiler,\"cc65 v %u.%u.%u\"", VER_MAJOR, VER_MINOR, VER_PATCH);
AddEmptyLine ();
+ /* If we're producing code for some other CPU, switch the command set */
+ if (CPU == CPU_65C02) {
+ AddCodeLine (".pc02");
+ }
+
/* Allow auto import for runtime library routines */
AddCodeLine (".autoimport\ton");
}
-
+
void g_leasp (int offs)
/* Fetch the address of the specified symbol into the primary register */
{
case CF_CHAR:
if (flags & CF_FORCECHAR) {
- AddCodeLine ("\tclc");
- AddCodeLine ("\tadc\t#$%02X", val & 0xFF);
+ if (CPU == CPU_65C02 && val <= 2) {
+ while (val--) {
+ AddCodeLine ("\tina");
+ }
+ } else {
+ AddCodeLine ("\tclc");
+ AddCodeLine ("\tadc\t#$%02X", val & 0xFF);
+ }
break;
}
/* FALLTHROUGH */
case CF_INT:
- if (FavourSize) {
+ if (CPU == CPU_65C02 && val == 1) {
+ AddCodeLine ("\tina");
+ AddCodeLine ("\tbne\t*+3");
+ AddCodeLine ("\tinx");
+ /* Tell the optimizer that the X register may be invalid */
+ AddCodeHint ("x:!");
+ } else if (FavourSize) {
/* Use jsr calls */
if (val <= 8) {
AddCodeLine ("\tjsr\tincax%u", val);
case CF_CHAR:
if (flags & CF_FORCECHAR) {
- AddCodeLine ("\tsec");
- AddCodeLine ("\tsbc\t#$%02X", val & 0xFF);
+ if (CPU == CPU_65C02 && val <= 2) {
+ while (val--) {
+ AddCodeLine ("\tdea");
+ }
+ } else {
+ AddCodeLine ("\tsec");
+ AddCodeLine ("\tsbc\t#$%02X", val & 0xFF);
+ }
break;
}
/* FALLTHROUGH */
#include "expr.h"
#include "function.h"
#include "global.h"
-#include "include.h"
+#include "incpath.h"
#include "io.h"
#include "litpool.h"
#include "macrotab.h"
--- /dev/null
+/*****************************************************************************/
+/* */
+/* cpu.c */
+/* */
+/* CPU type definitions */
+/* */
+/* */
+/* */
+/* (C) 2000 Ullrich von Bassewitz */
+/* Wacholderweg 14 */
+/* D-70597 Stuttgart */
+/* EMail: uz@musoftware.de */
+/* */
+/* */
+/* 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. */
+/* */
+/*****************************************************************************/
+
+
+
+#include "cpu.h"
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+/* Current CPU */
+CPUType CPU = CPU_6502;
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* cpu.h */
+/* */
+/* CPU type definitions */
+/* */
+/* */
+/* */
+/* (C) 2000 Ullrich von Bassewitz */
+/* Wacholderweg 14 */
+/* D-70597 Stuttgart */
+/* EMail: uz@musoftware.de */
+/* */
+/* */
+/* 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 CPU_H
+#define CPU_H
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+/* Supported CPUs */
+typedef enum CPUType {
+ CPU_6502,
+ CPU_65C02
+} CPUType;
+
+/* Current CPU */
+extern CPUType CPU;
+
+
+
+/* End of cpu.h */
+
+#endif
+
+
+
+++ /dev/null
-/*
- * include.c - Include file handling for cc65
- *
- * Ullrich von Bassewitz, 18.08.1998
- */
-
-
-
-#include <stdio.h>
-#include <string.h>
-#if defined(_MSC_VER)
-/* Microsoft compiler */
-# include <io.h>
-# define R_OK 4
-#else
-/* Anyone else */
-# include <unistd.h>
-#endif
-
-#include "mem.h"
-#include "include.h"
-
-
-
-/*****************************************************************************/
-/* data */
-/*****************************************************************************/
-
-
-
-static char* SysIncludePath = 0;
-static char* UserIncludePath = 0;
-
-
-
-/*****************************************************************************/
-/* code */
-/*****************************************************************************/
-
-
-
-static char* Add (char* Orig, const char* New)
-/* Create a new path from Orig and New, delete Orig, return the result */
-{
- unsigned OrigLen, NewLen;
- char* NewPath;
-
- /* Get the length of the original string */
- OrigLen = Orig? strlen (Orig) : 0;
-
- /* Get the length of the new path */
- NewLen = strlen (New);
-
- /* Check for a trailing path separator and remove it */
- if (NewLen > 0 && (New [NewLen-1] == '\\' || New [NewLen-1] == '/')) {
- --NewLen;
- }
-
- /* Allocate memory for the new string */
- NewPath = xmalloc (OrigLen + NewLen + 2);
-
- /* Copy the strings */
- memcpy (NewPath, Orig, OrigLen);
- memcpy (NewPath+OrigLen, New, NewLen);
- NewPath [OrigLen+NewLen+0] = ';';
- NewPath [OrigLen+NewLen+1] = '\0';
-
- /* Delete the original path */
- xfree (Orig);
-
- /* Return the new path */
- return NewPath;
-}
-
-
-
-static char* Find (const char* Path, const char* File)
-/* Search for a file in a list of directories. If found, return the complete
- * name including the path in a malloced data area, if not found, return 0.
- */
-{
- const char* P;
- int Max;
- char PathName [FILENAME_MAX];
-
- /* Initialize variables */
- Max = sizeof (PathName) - strlen (File) - 2;
- if (Max < 0) {
- return 0;
- }
- P = Path;
-
- /* Handle a NULL pointer as replacement for an empty string */
- if (P == 0) {
- P = "";
- }
-
- /* Start the search */
- while (*P) {
- /* Copy the next path element into the buffer */
- int Count = 0;
- while (*P != '\0' && *P != ';' && Count < Max) {
- PathName [Count++] = *P++;
- }
-
- /* Add a path separator and the filename */
- if (Count) {
- PathName [Count++] = '/';
- }
- strcpy (PathName + Count, File);
-
- /* Check if this file exists */
- if (access (PathName, R_OK) == 0) {
- /* The file exists */
- return xstrdup (PathName);
- }
-
- /* Skip a list separator if we have one */
- if (*P == ';') {
- ++P;
- }
- }
-
- /* Not found */
- return 0;
-}
-
-
-
-void AddIncludePath (const char* NewPath, unsigned Where)
-/* Add a new include path to the existing one */
-{
- /* Allow a NULL path */
- if (NewPath) {
- if (Where & INC_SYS) {
- SysIncludePath = Add (SysIncludePath, NewPath);
- }
- if (Where & INC_USER) {
- UserIncludePath = Add (UserIncludePath, NewPath);
- }
- }
-}
-
-
-
-char* FindInclude (const char* Name, unsigned Where)
-/* Find an include file. Return a pointer to a malloced area that contains
- * the complete path, if found, return 0 otherwise.
- */
-{
- if (Where & INC_SYS) {
- /* Search in the system include directories */
- return Find (SysIncludePath, Name);
- }
- if (Where & INC_USER) {
- /* Search in the user include directories */
- return Find (UserIncludePath, Name);
- }
- return 0;
-}
-
-
-
-
+++ /dev/null
-/*
- * include.h - Include file handling for cc65
- *
- * Ullrich von Bassewitz, 18.08.1998
- */
-
-
-
-#ifndef INCLUDE_H
-#define INCLUDE_H
-
-
-
-/*****************************************************************************/
-/* data */
-/*****************************************************************************/
-
-
-
-#define INC_SYS 0x0001 /* Add to system include path */
-#define INC_USER 0x0002 /* Add to user include path */
-
-
-
-/*****************************************************************************/
-/* code */
-/*****************************************************************************/
-
-
-
-void AddIncludePath (const char* NewPath, unsigned Where);
-/* Add a new include path to the existing one */
-
-char* FindInclude (const char* Name, unsigned Where);
-/* Find an include file. Return a pointer to a malloced area that contains
- * the complete path, if found, return 0 otherwise.
- */
-
-
-
-/* End of include.h */
-#endif
-
-
-
--- /dev/null
+/*****************************************************************************/
+/* */
+/* incpath.c */
+/* */
+/* Include path handling for cc65 */
+/* */
+/* */
+/* */
+/* (C) 2000 Ullrich von Bassewitz */
+/* Wacholderweg 14 */
+/* D-70597 Stuttgart */
+/* EMail: uz@musoftware.de */
+/* */
+/* */
+/* 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. */
+/* */
+/*****************************************************************************/
+
+
+
+#include <stdio.h>
+#include <string.h>
+#if defined(_MSC_VER)
+/* Microsoft compiler */
+# include <io.h>
+# define R_OK 4
+#else
+/* Anyone else */
+# include <unistd.h>
+#endif
+
+#include "mem.h"
+#include "incpath.h"
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+static char* SysIncludePath = 0;
+static char* UserIncludePath = 0;
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+static char* Add (char* Orig, const char* New)
+/* Create a new path from Orig and New, delete Orig, return the result */
+{
+ unsigned OrigLen, NewLen;
+ char* NewPath;
+
+ /* Get the length of the original string */
+ OrigLen = Orig? strlen (Orig) : 0;
+
+ /* Get the length of the new path */
+ NewLen = strlen (New);
+
+ /* Check for a trailing path separator and remove it */
+ if (NewLen > 0 && (New [NewLen-1] == '\\' || New [NewLen-1] == '/')) {
+ --NewLen;
+ }
+
+ /* Allocate memory for the new string */
+ NewPath = xmalloc (OrigLen + NewLen + 2);
+
+ /* Copy the strings */
+ memcpy (NewPath, Orig, OrigLen);
+ memcpy (NewPath+OrigLen, New, NewLen);
+ NewPath [OrigLen+NewLen+0] = ';';
+ NewPath [OrigLen+NewLen+1] = '\0';
+
+ /* Delete the original path */
+ xfree (Orig);
+
+ /* Return the new path */
+ return NewPath;
+}
+
+
+
+static char* Find (const char* Path, const char* File)
+/* Search for a file in a list of directories. If found, return the complete
+ * name including the path in a malloced data area, if not found, return 0.
+ */
+{
+ const char* P;
+ int Max;
+ char PathName [FILENAME_MAX];
+
+ /* Initialize variables */
+ Max = sizeof (PathName) - strlen (File) - 2;
+ if (Max < 0) {
+ return 0;
+ }
+ P = Path;
+
+ /* Handle a NULL pointer as replacement for an empty string */
+ if (P == 0) {
+ P = "";
+ }
+
+ /* Start the search */
+ while (*P) {
+ /* Copy the next path element into the buffer */
+ int Count = 0;
+ while (*P != '\0' && *P != ';' && Count < Max) {
+ PathName [Count++] = *P++;
+ }
+
+ /* Add a path separator and the filename */
+ if (Count) {
+ PathName [Count++] = '/';
+ }
+ strcpy (PathName + Count, File);
+
+ /* Check if this file exists */
+ if (access (PathName, R_OK) == 0) {
+ /* The file exists */
+ return xstrdup (PathName);
+ }
+
+ /* Skip a list separator if we have one */
+ if (*P == ';') {
+ ++P;
+ }
+ }
+
+ /* Not found */
+ return 0;
+}
+
+
+
+void AddIncludePath (const char* NewPath, unsigned Where)
+/* Add a new include path to the existing one */
+{
+ /* Allow a NULL path */
+ if (NewPath) {
+ if (Where & INC_SYS) {
+ SysIncludePath = Add (SysIncludePath, NewPath);
+ }
+ if (Where & INC_USER) {
+ UserIncludePath = Add (UserIncludePath, NewPath);
+ }
+ }
+}
+
+
+
+char* FindInclude (const char* Name, unsigned Where)
+/* Find an include file. Return a pointer to a malloced area that contains
+ * the complete path, if found, return 0 otherwise.
+ */
+{
+ if (Where & INC_SYS) {
+ /* Search in the system include directories */
+ return Find (SysIncludePath, Name);
+ }
+ if (Where & INC_USER) {
+ /* Search in the user include directories */
+ return Find (UserIncludePath, Name);
+ }
+ return 0;
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* incpath.h */
+/* */
+/* Include path handling for cc65 */
+/* */
+/* */
+/* */
+/* (C) 2000 Ullrich von Bassewitz */
+/* Wacholderweg 14 */
+/* D-70597 Stuttgart */
+/* EMail: uz@musoftware.de */
+/* */
+/* */
+/* 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 INCPATH_H
+#define INCPATH_H
+
+
+
+/*****************************************************************************/
+/* Data */
+/*****************************************************************************/
+
+
+
+#define INC_SYS 0x0001 /* Add to system include path */
+#define INC_USER 0x0002 /* Add to user include path */
+
+
+
+/*****************************************************************************/
+/* Code */
+/*****************************************************************************/
+
+
+
+void AddIncludePath (const char* NewPath, unsigned Where);
+/* Add a new include path to the existing one */
+
+char* FindInclude (const char* Name, unsigned Where);
+/* Find an include file. Return a pointer to a malloced area that contains
+ * the complete path, if found, return 0 otherwise.
+ */
+
+
+
+/* End of incpath.h */
+#endif
+
+
+
-int readline (void)
+int NextLine (void)
/* Get a line from the current input. Returns -1 on end of file. */
{
unsigned Len;
* pointer (no end of line check is performed).
*/
-int readline (void);
+int NextLine (void);
/* Get a line from the current input. Returns -1 on end of file. */
-/* CC65 main program */
+/*****************************************************************************/
+/* */
+/* main.c */
+/* */
+/* cc65 main program */
+/* */
+/* */
+/* */
+/* (C) 2000 Ullrich von Bassewitz */
+/* Wacholderweg 14 */
+/* D-70597 Stuttgart */
+/* EMail: uz@musoftware.de */
+/* */
+/* */
+/* 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. */
+/* */
+/*****************************************************************************/
+
+
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
+#include "../common/cmdline.h"
#include "../common/version.h"
#include "asmcode.h"
#include "compile.h"
+#include "cpu.h"
#include "error.h"
#include "global.h"
-#include "include.h"
+#include "incpath.h"
#include "io.h"
#include "macrotab.h"
#include "mem.h"
-static void usage (int ExitCode)
+static void Usage (void)
{
- fputs ("Usage: cc65 [options] file\n"
- "\t-d\t\tDebug mode\n"
- "\t-g\t\tAdd debug info to object files\n"
- "\t-h\t\tPrint this help\n"
- "\t-j\t\tDefault characters are signed\n"
- "\t-o name\t\tName the output file\n"
- "\t-tx\t\tSet target system x\n"
- "\t-v\t\tVerbose mode\n"
- "\t-A\t\tStrict ANSI mode\n"
- "\t-Cl\t\tMake local variables static\n"
- "\t-Dsym[=defn]\tDefine a symbol\n"
- "\t-I path\t\tSet include directory\n"
- "\t-O\t\tOptimize code\n"
- "\t-Oi\t\tOptimize code, inline more code\n"
- "\t-Or\t\tEnable register variables\n"
- "\t-Os\t\tInline some known functions\n"
- "\t-T\t\tInclude source as comment\n"
- "\t-V\t\tPrint version number\n"
- "\t-W\t\tSuppress warnings\n",
- stderr);
- exit (ExitCode);
-}
-
-
-
-static char* GetArg (int* ArgNum, char* argv [], unsigned Len)
-/* Get an option argument */
-{
- char* Arg = argv [*ArgNum];
- if (Arg [Len] != '\0') {
- /* Argument appended */
- return Arg + Len;
- } else {
- /* Separate argument */
- Arg = argv [*ArgNum + 1];
- if (Arg == 0) {
- /* End of arguments */
- fprintf (stderr, "Option requires an argument: %s\n", argv [*ArgNum]);
- exit (EXIT_FAILURE);
- }
- ++(*ArgNum);
- return Arg;
- }
+ fprintf (stderr,
+ "Usage: cc65 [options] file\n"
+ "Short options:\n"
+ " -d\t\t\tDebug mode\n"
+ " -g\t\t\tAdd debug info to object file\n"
+ " -h\t\t\tPrint this help\n"
+ " -j\t\t\tDefault characters are signed\n"
+ " -o name\t\tName the output file\n"
+ " -t sys\t\tSet the target system\n"
+ " -v\t\t\tIncrease verbosity\n"
+ " -A\t\t\tStrict ANSI mode\n"
+ " -Cl\t\t\tMake local variables static\n"
+ " -Dsym[=defn]\t\tDefine a symbol\n"
+ " -I path\t\tSet an include directory search path\n"
+ " -O\t\t\tOptimize code\n"
+ " -Oi\t\t\tOptimize code, inline more code\n"
+ " -Or\t\t\tEnable register variables\n"
+ " -Os\t\t\tInline some known functions\n"
+ " -T\t\t\tInclude source as comment\n"
+ " -V\t\t\tPrint the compiler version number\n"
+ " -W\t\t\tSuppress warnings\n"
+ "\n"
+ "Long options:\n"
+ " --ansi\t\tStrict ANSI mode\n"
+ " --cpu type\t\tSet cpu type\n"
+ " --debug-info\t\tAdd debug info to object file\n"
+ " --help\t\tHelp (this text)\n"
+ " --include-dir dir\tSet an include directory search path\n"
+ " --signed-chars\tDefault characters are signed\n"
+ " --target sys\t\tSet the target system\n"
+ " --verbose\t\tIncrease verbosity\n"
+ " --version\t\tPrint the compiler version number\n");
}
-/* Define a CBM system */
static void cbmsys (const char* sys)
+/* Define a CBM system */
{
AddNumericMacro ("__CBM__", 1);
AddNumericMacro (sys, 1);
-/* Define a target system */
static void SetSys (const char* Sys)
+/* Define a target system */
{
switch (Target = MapSys (Sys)) {
break;
case TGT_ATARI:
- AddNumericMacro ("__ATARI__", 1);
+ AddNumericMacro ("__ATARI__", 1);
break;
case TGT_C64:
default:
fputs ("Unknown system type\n", stderr);
- usage (EXIT_FAILURE);
+ exit (EXIT_FAILURE);
}
}
-static void InvSym (const char* Def)
-/* Print an error about an invalid macro definition and die */
-{
- fprintf (stderr, "Invalid macro definition: `%s'\n", Def);
- exit (EXIT_FAILURE);
-}
-
-
-
static void DefineSym (const char* Def)
/* Define a symbol on the command line */
{
/* The symbol must start with a character or underline */
if (Def [0] != '_' && !isalpha (Def [0])) {
- InvSym (Def);
+ InvDef (Def);
}
/* Check the symbol name */
/* Do we have a value given? */
if (*P != '=') {
if (*P != '\0') {
- InvSym (Def);
+ InvDef (Def);
}
/* No value given. Define the macro with the value 1 */
AddNumericMacro (Def, 1);
/* Define this as a macro */
AddTextMacro (S, Q);
- /* Release the allocated memory */
- xfree (S);
+ /* Release the allocated memory */
+ xfree (S);
+ }
+}
+
+
+
+static void OptAnsi (const char* Opt, const char* Arg)
+/* Compile in strict ANSI mode */
+{
+ ANSI = 1;
+}
+
+
+
+static void OptCPU (const char* Opt, const char* Arg)
+/* Handle the --cpu option */
+{
+ if (Arg == 0) {
+ NeedArg (Opt);
+ }
+ if (strcmp (Arg, "6502") == 0) {
+ CPU = CPU_6502;
+ } else if (strcmp (Arg, "65C02") == 0) {
+ CPU = CPU_65C02;
+ } else {
+ fprintf (stderr, "Invalid CPU: `%s'\n", Arg);
+ exit (EXIT_FAILURE);
+ }
+}
+
+
+
+static void OptDebugInfo (const char* Opt, const char* Arg)
+/* Add debug info to the object file */
+{
+ DebugInfo = 1;
+}
+
+
+
+static void OptHelp (const char* Opt, const char* Arg)
+/* Print usage information and exit */
+{
+ Usage ();
+ exit (EXIT_SUCCESS);
+}
+
+
+
+static void OptIncludeDir (const char* Opt, const char* Arg)
+/* Add an include search path */
+{
+ if (Arg == 0) {
+ NeedArg (Opt);
+ }
+ AddIncludePath (Arg, INC_SYS | INC_USER);
+}
+
+
+
+static void OptSignedChars (const char* Opt, const char* Arg)
+/* Make default characters signed */
+{
+ SignedChars = 1;
+}
+
+
+
+static void OptTarget (const char* Opt, const char* Arg)
+/* Set the target system */
+{
+ if (Arg == 0) {
+ NeedArg (Opt);
}
+ SetSys (Arg);
+}
+
+
+
+static void OptVerbose (const char* Opt, const char* Arg)
+/* Increase verbosity */
+{
+ ++Verbose;
}
-int main (int argc, char **argv)
+static void OptVersion (const char* Opt, const char* Arg)
+/* Print the assembler version */
{
- int i;
- char *argp;
+ fprintf (stderr,
+ "cc65 V%u.%u.%u\n",
+ VER_MAJOR, VER_MINOR, VER_PATCH);
+}
+
+
+
+int main (int argc, char* argv[])
+{
+ /* Program long options */
+ static const LongOpt OptTab[] = {
+ { "--ansi", 0, OptAnsi },
+ { "--cpu", 1, OptCPU },
+ { "--debug-info", 0, OptDebugInfo },
+ { "--help", 0, OptHelp },
+ { "--include-dir", 1, OptIncludeDir },
+ { "--signed-chars", 0, OptSignedChars },
+ { "--target", 1, OptTarget },
+ { "--verbose", 0, OptVerbose },
+ { "--version", 0, OptVersion },
+ };
+
+ int I;
char out_name [256];
- char* p;
/* Initialize the output file name */
out_name [0] = '\0';
fin = NULL;
+ /* Initialize the cmdline module */
+ InitCmdLine (argc, argv);
+
/* Parse the command line */
- for (i = 1; i < argc; i++) {
- if (*(argp = argv[i]) == '-') {
- switch (argp[1]) {
+ I = 1;
+ while (I < argc) {
+
+ const char* P;
+
+ /* Get the argument */
+ const char* Arg = argv [I];
+
+ /* Check for an option */
+ if (Arg [0] == '-') {
+
+ switch (Arg [1]) {
+
+ case '-':
+ LongOption (&I, OptTab, sizeof(OptTab)/sizeof(OptTab[0]));
+ break;
case 'd': /* debug mode */
Debug = 1;
case 'h':
case '?':
- usage (EXIT_SUCCESS);
+ OptHelp (Arg, 0);
break;
case 'g':
- DebugInfo = 1;
+ OptDebugInfo (Arg, 0);
break;
case 'j':
- SignedChars = 1;
+ OptSignedChars (Arg, 0);
break;
- case 'o':
- strcpy (out_name, GetArg (&i, argv, 2));
+ case 'o':
+ strcpy (out_name, GetArg (&I, 2));
break;
case 't':
- SetSys (GetArg (&i, argv, 2));
+ OptTarget (Arg, GetArg (&I, 2));
break;
case 'v':
- ++Verbose;
+ OptVerbose (Arg, 0);
break;
case 'A':
- ANSI = 1;
+ OptAnsi (Arg, 0);
break;
case 'C':
- p = argp + 2;
- while (*p) {
- switch (*p++) {
- case 'l':
- LocalsAreStatic = 1;
- break;
- }
+ P = Arg + 2;
+ while (*P) {
+ switch (*P++) {
+ case 'l':
+ LocalsAreStatic = 1;
+ break;
+ }
}
break;
case 'D':
- DefineSym (GetArg (&i, argv, 2));
+ DefineSym (GetArg (&I, 2));
break;
case 'I':
- AddIncludePath (GetArg (&i, argv, 2), INC_SYS | INC_USER);
+ OptIncludeDir (Arg, GetArg (&I, 2));
break;
case 'O':
Optimize = 1;
- p = argp + 2;
- while (*p) {
- switch (*p++) {
- case 'f':
- sscanf (p, "%lx", (long*) &OptDisable);
- break;
- case 'i':
- FavourSize = 0;
- break;
- case 'r':
- EnableRegVars = 1;
+ P = Arg + 2;
+ while (*P) {
+ switch (*P++) {
+ case 'f':
+ sscanf (P, "%lx", (long*) &OptDisable);
+ break;
+ case 'i':
+ FavourSize = 0;
+ break;
+ case 'r':
+ EnableRegVars = 1;
break;
case 's':
- InlineStdFuncs = 1;
+ InlineStdFuncs = 1;
break;
}
}
break;
case 'V':
- fprintf (stderr, "cc65 V%u.%u.%u\n",
- VER_MAJOR, VER_MINOR, VER_PATCH);
+ OptVersion (Arg, 0);
break;
case 'W':
break;
default:
- fprintf (stderr, "Invalid option %s\n", argp);
- usage (EXIT_FAILURE);
+ UnknownOption (Arg);
+ break;
}
} else {
if (fin) {
fprintf (stderr, "additional file specs ignored\n");
} else {
- fin = xstrdup (argp);
+ fin = xstrdup (Arg);
inp = fopen (fin, "r");
if (inp == 0) {
Fatal (FAT_CANNOT_OPEN_INPUT, strerror (errno));
}
}
}
+
+ /* Next argument */
+ ++I;
}
+
+ /* Did we have a file spec on the command line? */
if (!fin) {
fprintf (stderr, "%s: No input files\n", argv [0]);
exit (EXIT_FAILURE);
/* Create the output file name. We should really have
* some checks for string overflow, but I'll drop this because of the
* additional code size it would need (as in other places). Sigh.
+ * #### To be removed
*/
if (out_name [0] == '\0') {
+ char* p;
/* No output name given, create default */
strcpy (out_name, fin);
if ((p = strrchr (out_name, '.'))) {
}
+
check.o \
codegen.o \
compile.o \
+ cpu.o \
ctrans.o \
datatype.o \
declare.o \
global.o \
goto.o \
ident.o \
- include.o \
+ incpath.o \
io.o \
litpool.o \
locals.o \
check.obj \
codegen.obj \
compile.obj \
+ cpu.obj \
ctrans.obj \
datatype.obj \
declare.obj \
global.obj \
goto.obj \
ident.obj \
- include.obj \
+ incpath.obj \
io.obj \
litpool.obj \
locals.obj \
FILE check.obj
FILE codegen.obj
FILE compile.obj
+FILE cpu.obj
FILE ctrans.obj
FILE datatype.obj
FILE declare.obj
FILE global.obj
FILE goto.obj
FILE ident.obj
-FILE include.obj
+FILE incpath.obj
FILE io.obj
FILE litpool.obj
FILE locals.obj
#include "asmlabel.h"
#include "asmline.h"
#include "check.h"
+#include "cpu.h"
#include "error.h"
#include "global.h"
#include "io.h"
{ "\tcmp\t", 0, REG_A, REG_NONE },
{ "\tcpx\t", 0, REG_X, REG_NONE },
{ "\tcpy\t", 0, REG_Y, REG_NONE },
+ { "\tdea", 1, REG_A, REG_NONE },
+ { "\tdec\ta", 1, REG_A, REG_NONE },
{ "\tdec\t", 0, REG_NONE, REG_NONE },
{ "\tdex", 1, REG_X, REG_NONE },
{ "\tdey", 1, REG_Y, REG_NONE },
{ "\teor\t", 0, REG_A, REG_NONE },
+ { "\tina", 1, REG_A, REG_NONE },
+ { "\tinc\ta", 1, REG_A, REG_NONE },
{ "\tinc\t", 0, REG_NONE, REG_NONE },
{ "\tinx", 1, REG_X, REG_NONE },
{ "\tiny", 1, REG_Y, REG_NONE },
{ "\tsta\t", 0, REG_A, REG_NONE },
{ "\tstx\t", 0, REG_X, REG_NONE },
{ "\tsty\t", 0, REG_Y, REG_NONE },
+ { "\tstz\t", 0, REG_NONE, REG_NONE },
{ "\ttax", 1, REG_A, REG_X },
{ "\ttay", 1, REG_A, REG_Y },
{ "\ttsx", 1, REG_NONE, REG_X },
-static int IsXIndAddrMode (Line* L)
+static int IsXAddrMode (Line* L)
/* Return true if the given line does use the X register */
{
unsigned Len = strlen (L->Line);
-static int NoXIndAddrMode (Line* L)
+static int NoXAddrMode (Line* L)
/* Return true if the given line does use the X register */
{
- return !IsXIndAddrMode (L);
+ return !IsXAddrMode (L);
}
-static int IsYIndAddrMode (Line* L)
+static int IsYAddrMode (Line* L)
/* Return true if the given line does use the Y register */
{
unsigned Len = strlen (L->Line);
static unsigned EstimateSize (Line* L)
/* Estimate the size of an instruction */
{
- static const char* Transfers [] = {
+ static const char* OneByteCmds [] = {
+ "\tdea",
+ "\tdex",
+ "\tdey",
+ "\tina",
+ "\tinx",
+ "\tiny"
"\ttax",
"\ttay",
"\ttsx",
if (LineMatchX (L, LongBranches) >= 0) {
return 5;
}
- if (LineMatchX (L, Transfers) >= 0) {
+ if (LineMatchX (L, OneByteCmds) >= 0) {
return 1;
}
return 3;
/* Evaluate the use flags, check for addressing modes */
R = CmdDesc[I].Use;
- if (IsXIndAddrMode (L)) {
+ if (IsXAddrMode (L)) {
R |= REG_X;
- } else if (IsYIndAddrMode (L)) {
+ } else if (IsYAddrMode (L)) {
R |= REG_Y;
}
if (R) {
(Cond = TosCmpFunc (L2[4])) >= 0) {
/* Replace it */
- if (IsXIndAddrMode (L2[0])) {
+ if (IsXAddrMode (L2[0])) {
/* The load is X indirect, so we may not remove the load
* of the X register.
*/
Offs = GetHexNum (L2[2]->Line+7) - 2;
/* Replace it */
- if (IsXIndAddrMode (L2[0])) {
+ if (IsXAddrMode (L2[0])) {
/* The load is X indirect, so we may not remove the load
* of the X register.
*/
LineFullMatch (L2 [1], "\tjsr\tpushax")) {
/* Be sure, X is not used in the load */
- if (NoXIndAddrMode (L2 [0])) {
+ if (NoXAddrMode (L2 [0])) {
/* Replace the subroutine call */
L2 [1] = ReplaceLine (L2 [1], "\tjsr\tpusha0");
LineMatch (L2 [1], "\tcmp\t#$")) {
/* Be sure, X is not used in the load */
- if (NoXIndAddrMode (L2 [0])) {
+ if (NoXAddrMode (L2 [0])) {
/* Remove the unnecessary load */
FreeLine (L);
LineFullMatch (L2 [1], "\tjsr\tbnega")) {
/* Be sure, X is not used in the load */
- if (NoXIndAddrMode (L2 [0])) {
+ if (NoXAddrMode (L2 [0])) {
/* Remove the unnecessary load */
FreeLine (L);
if (A != -1) {
A = (A << 1) & 0xFF;
}
+ } else if (CPU == CPU_65C02 && LineFullMatch (L, "\tdea")) {
+ DEC (A, 1);
} else if (LineFullMatch (L, "\tdex")) {
DEC (X, 1);
} else if (LineFullMatch (L, "\tdey")) {
DEC (Y, 1);
} else if (LineMatch (L, "\teor")) {
A = -1;
+ } else if (CPU == CPU_65C02 && LineFullMatch (L, "\tina")) {
+ INC (A, 1);
} else if (LineFullMatch (L, "\tinx")) {
INC (X, 1);
} else if (LineFullMatch (L, "\tiny")) {
/* The value loaded is not used later, remove it */
Delete = 1;
} else if (LineMatch (L, "\tlda\t(")) {
- if (IsXIndAddrMode (L)) {
+ if (IsXAddrMode (L)) {
/* lda (zp,x) - if Y and X are both zero, replace by
* load indirect y and save one cycle in some cases.
*/
} else if (NewVal == Y) {
/* Requested value is already in Y */
L = ReplaceLine (L, "\ttya");
+ } else if (CPU == CPU_65C02 && A != -1) {
+ /* Try ina/dea operators of 65C02 */
+ if (NewVal == ((A - 1) & 0xFF)) {
+ L = ReplaceLine (L, "\tdea");
+ } else if (NewVal == ((A + 1) & 0xFF)) {
+ L = ReplaceLine (L, "\tina");
+ }
}
/* Anyway, the new value is now in A */
A = NewVal;
A = X = Y = -1;
} else if (LineMatch (L, "\tsbc\t")) {
A = -1;
+ } else if (CPU == CPU_65C02 && LineMatch (L, "\tst")) {
+ /* Try to replace by stz if possible */
+ if (A == 0 && LineMatch (L, "\tsta\t")) {
+ /* Not indirect and not Y allowed */
+ if (L->Line[5] != '(' && !IsYAddrMode (L)) {
+ L->Line[3] = 'z';
+ }
+ } else if (X == 0 && LineMatch (L, "\tstx\t")) {
+ /* absolute,y not allowed */
+ if (!IsYAddrMode (L)) {
+ L->Line[3] = 'z';
+ }
+ } else if (Y == 0 && LineMatch (L, "\tsty\t")) {
+ /* sty and stz share all addressing modes */
+ L->Line[3] = 'z';
+ }
} else if (LineFullMatch (L, "\ttax")) {
if (A != -1 && X == A) {
/* Load has no effect */
#include "expr.h"
#include "global.h"
#include "ident.h"
-#include "include.h"
+#include "incpath.h"
#include "io.h"
#include "macrotab.h"
#include "mem.h"
gch ();
while (*lptr != '*' || nch () != '/') {
if (*lptr == '\0') {
- if (readline () == 0) {
+ if (NextLine () == 0) {
PPError (ERR_EOF_IN_COMMENT, StartingLine);
return;
}
skipblank ();
} else if (C == '\0') {
/* End of line inside macro argument list - read next line */
- if (readline () == 0) {
+ if (NextLine () == 0) {
return 0;
}
} else {
}
}
- if (readline () == 0) {
+ if (NextLine () == 0) {
if (i_ifdef >= 0) {
PPError (ERR_CPP_ENDIF_EXPECTED);
}
{
while (1) {
while (*lptr == 0) {
- if (readline () == 0) {
+ if (NextLine () == 0) {
return 0;
}
preprocess ();