mirror of
https://github.com/cc65/cc65.git
synced 2025-02-26 23:30:03 +00:00
Some basic support for the 65C02 CPU.
Use the command line module from common/ and support long options. Rename the include module to incpath (as in the assembler). git-svn-id: svn://svn.cc65.org/cc65/trunk@67 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
f1feae3a97
commit
114bc5a370
@ -41,6 +41,7 @@
|
||||
#include "asmcode.h"
|
||||
#include "asmlabel.h"
|
||||
#include "check.h"
|
||||
#include "cpu.h"
|
||||
#include "error.h"
|
||||
#include "global.h"
|
||||
#include "io.h"
|
||||
@ -157,6 +158,11 @@ void g_preamble (void)
|
||||
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");
|
||||
|
||||
@ -920,7 +926,7 @@ void g_getind (unsigned flags, unsigned offs)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void g_leasp (int offs)
|
||||
/* Fetch the address of the specified symbol into the primary register */
|
||||
{
|
||||
@ -3096,14 +3102,26 @@ void g_inc (unsigned flags, unsigned long val)
|
||||
|
||||
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);
|
||||
@ -3172,8 +3190,14 @@ void g_dec (unsigned flags, unsigned long 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 */
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include "expr.h"
|
||||
#include "function.h"
|
||||
#include "global.h"
|
||||
#include "include.h"
|
||||
#include "incpath.h"
|
||||
#include "io.h"
|
||||
#include "litpool.h"
|
||||
#include "macrotab.h"
|
||||
|
50
src/cc65/cpu.c
Normal file
50
src/cc65/cpu.c
Normal file
@ -0,0 +1,50 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* 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;
|
||||
|
||||
|
||||
|
63
src/cc65/cpu.h
Normal file
63
src/cc65/cpu.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* 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
|
||||
|
||||
|
||||
|
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
|
||||
|
@ -1,8 +1,35 @@
|
||||
/*
|
||||
* include.c - Include file handling for cc65
|
||||
*
|
||||
* Ullrich von Bassewitz, 18.08.1998
|
||||
*/
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* 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. */
|
||||
/* */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
@ -18,12 +45,12 @@
|
||||
#endif
|
||||
|
||||
#include "mem.h"
|
||||
#include "include.h"
|
||||
#include "incpath.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* data */
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -34,7 +61,7 @@ static char* UserIncludePath = 0;
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* code */
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
@ -161,4 +188,3 @@ char* FindInclude (const char* Name, unsigned Where)
|
||||
|
||||
|
||||
|
||||
|
72
src/cc65/incpath.h
Normal file
72
src/cc65/incpath.h
Normal file
@ -0,0 +1,72 @@
|
||||
/*****************************************************************************/
|
||||
/* */
|
||||
/* 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
|
||||
|
||||
|
||||
|
@ -112,7 +112,7 @@ static void CloseInclude (void)
|
||||
|
||||
|
||||
|
||||
int readline (void)
|
||||
int NextLine (void)
|
||||
/* Get a line from the current input. Returns -1 on end of file. */
|
||||
{
|
||||
unsigned Len;
|
||||
|
@ -73,7 +73,7 @@ int gch (void);
|
||||
* 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. */
|
||||
|
||||
|
||||
|
348
src/cc65/main.c
348
src/cc65/main.c
@ -1,4 +1,37 @@
|
||||
/* 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>
|
||||
@ -6,13 +39,15 @@
|
||||
#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"
|
||||
@ -50,57 +85,46 @@ static const char* TargetNames [] = {
|
||||
|
||||
|
||||
|
||||
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);
|
||||
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");
|
||||
}
|
||||
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Define a CBM system */
|
||||
static void cbmsys (const char* sys)
|
||||
/* Define a CBM system */
|
||||
{
|
||||
AddNumericMacro ("__CBM__", 1);
|
||||
AddNumericMacro (sys, 1);
|
||||
@ -133,8 +157,8 @@ static int MapSys (const char* Name)
|
||||
|
||||
|
||||
|
||||
/* Define a target system */
|
||||
static void SetSys (const char* Sys)
|
||||
/* Define a target system */
|
||||
{
|
||||
switch (Target = MapSys (Sys)) {
|
||||
|
||||
@ -142,7 +166,7 @@ static void SetSys (const char* Sys)
|
||||
break;
|
||||
|
||||
case TGT_ATARI:
|
||||
AddNumericMacro ("__ATARI__", 1);
|
||||
AddNumericMacro ("__ATARI__", 1);
|
||||
break;
|
||||
|
||||
case TGT_C64:
|
||||
@ -184,21 +208,12 @@ static void SetSys (const char* Sys)
|
||||
|
||||
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 */
|
||||
{
|
||||
@ -206,7 +221,7 @@ static void DefineSym (const char* Def)
|
||||
|
||||
/* The symbol must start with a character or underline */
|
||||
if (Def [0] != '_' && !isalpha (Def [0])) {
|
||||
InvSym (Def);
|
||||
InvDef (Def);
|
||||
}
|
||||
|
||||
/* Check the symbol name */
|
||||
@ -217,7 +232,7 @@ static void DefineSym (const char* Def)
|
||||
/* 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);
|
||||
@ -236,29 +251,147 @@ static void DefineSym (const char* Def)
|
||||
/* Define this as a macro */
|
||||
AddTextMacro (S, Q);
|
||||
|
||||
/* Release the allocated memory */
|
||||
xfree (S);
|
||||
/* Release the allocated memory */
|
||||
xfree (S);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main (int argc, char **argv)
|
||||
static void OptAnsi (const char* Opt, const char* Arg)
|
||||
/* Compile in strict ANSI mode */
|
||||
{
|
||||
int i;
|
||||
char *argp;
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void OptVersion (const char* Opt, const char* Arg)
|
||||
/* Print the assembler version */
|
||||
{
|
||||
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;
|
||||
@ -266,68 +399,68 @@ int main (int argc, char **argv)
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -338,8 +471,7 @@ int main (int argc, char **argv)
|
||||
break;
|
||||
|
||||
case 'V':
|
||||
fprintf (stderr, "cc65 V%u.%u.%u\n",
|
||||
VER_MAJOR, VER_MINOR, VER_PATCH);
|
||||
OptVersion (Arg, 0);
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
@ -347,21 +479,26 @@ int main (int argc, char **argv)
|
||||
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);
|
||||
@ -370,8 +507,10 @@ int main (int argc, char **argv)
|
||||
/* 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, '.'))) {
|
||||
@ -414,3 +553,4 @@ int main (int argc, char **argv)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -16,6 +16,7 @@ OBJS = anonname.o \
|
||||
check.o \
|
||||
codegen.o \
|
||||
compile.o \
|
||||
cpu.o \
|
||||
ctrans.o \
|
||||
datatype.o \
|
||||
declare.o \
|
||||
@ -26,7 +27,7 @@ OBJS = anonname.o \
|
||||
global.o \
|
||||
goto.o \
|
||||
ident.o \
|
||||
include.o \
|
||||
incpath.o \
|
||||
io.o \
|
||||
litpool.o \
|
||||
locals.o \
|
||||
|
@ -70,6 +70,7 @@ OBJS = anonname.obj \
|
||||
check.obj \
|
||||
codegen.obj \
|
||||
compile.obj \
|
||||
cpu.obj \
|
||||
ctrans.obj \
|
||||
datatype.obj \
|
||||
declare.obj \
|
||||
@ -80,7 +81,7 @@ OBJS = anonname.obj \
|
||||
global.obj \
|
||||
goto.obj \
|
||||
ident.obj \
|
||||
include.obj \
|
||||
incpath.obj \
|
||||
io.obj \
|
||||
litpool.obj \
|
||||
locals.obj \
|
||||
@ -126,6 +127,7 @@ FILE asmline.obj
|
||||
FILE check.obj
|
||||
FILE codegen.obj
|
||||
FILE compile.obj
|
||||
FILE cpu.obj
|
||||
FILE ctrans.obj
|
||||
FILE datatype.obj
|
||||
FILE declare.obj
|
||||
@ -136,7 +138,7 @@ FILE function.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
|
||||
|
@ -40,6 +40,7 @@
|
||||
#include "asmlabel.h"
|
||||
#include "asmline.h"
|
||||
#include "check.h"
|
||||
#include "cpu.h"
|
||||
#include "error.h"
|
||||
#include "global.h"
|
||||
#include "io.h"
|
||||
@ -123,10 +124,14 @@ static const struct {
|
||||
{ "\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 },
|
||||
@ -164,6 +169,7 @@ static const struct {
|
||||
{ "\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 },
|
||||
@ -559,7 +565,7 @@ static int IsCondJump (Line* L)
|
||||
|
||||
|
||||
|
||||
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);
|
||||
@ -569,15 +575,15 @@ static int IsXIndAddrMode (Line* L)
|
||||
|
||||
|
||||
|
||||
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);
|
||||
@ -779,7 +785,13 @@ static unsigned EstimateDataSize (Line* L, unsigned Chunk)
|
||||
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",
|
||||
@ -819,7 +831,7 @@ static unsigned EstimateSize (Line* L)
|
||||
if (LineMatchX (L, LongBranches) >= 0) {
|
||||
return 5;
|
||||
}
|
||||
if (LineMatchX (L, Transfers) >= 0) {
|
||||
if (LineMatchX (L, OneByteCmds) >= 0) {
|
||||
return 1;
|
||||
}
|
||||
return 3;
|
||||
@ -1141,9 +1153,9 @@ static unsigned RVUInt2 (Line* L,
|
||||
|
||||
/* 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) {
|
||||
@ -1323,7 +1335,7 @@ static void OptCompares1 (void)
|
||||
(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.
|
||||
*/
|
||||
@ -1377,7 +1389,7 @@ static void OptCompares1 (void)
|
||||
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.
|
||||
*/
|
||||
@ -1637,7 +1649,7 @@ static void OptLoads (void)
|
||||
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");
|
||||
@ -1667,7 +1679,7 @@ static void OptLoads (void)
|
||||
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);
|
||||
@ -1693,7 +1705,7 @@ static void OptLoads (void)
|
||||
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);
|
||||
@ -3630,12 +3642,16 @@ static Line* OptOneBlock (Line* 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")) {
|
||||
@ -3949,7 +3965,7 @@ static Line* OptOneBlock (Line* L)
|
||||
/* 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.
|
||||
*/
|
||||
@ -3982,6 +3998,13 @@ static Line* OptOneBlock (Line* L)
|
||||
} 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;
|
||||
@ -4066,6 +4089,22 @@ static Line* OptOneBlock (Line* L)
|
||||
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 */
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include "expr.h"
|
||||
#include "global.h"
|
||||
#include "ident.h"
|
||||
#include "include.h"
|
||||
#include "incpath.h"
|
||||
#include "io.h"
|
||||
#include "macrotab.h"
|
||||
#include "mem.h"
|
||||
@ -89,7 +89,7 @@ static void comment (void)
|
||||
gch ();
|
||||
while (*lptr != '*' || nch () != '/') {
|
||||
if (*lptr == '\0') {
|
||||
if (readline () == 0) {
|
||||
if (NextLine () == 0) {
|
||||
PPError (ERR_EOF_IN_COMMENT, StartingLine);
|
||||
return;
|
||||
}
|
||||
@ -283,7 +283,7 @@ static int MacroCall (Macro* M)
|
||||
skipblank ();
|
||||
} else if (C == '\0') {
|
||||
/* End of line inside macro argument list - read next line */
|
||||
if (readline () == 0) {
|
||||
if (NextLine () == 0) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
@ -864,7 +864,7 @@ void preprocess (void)
|
||||
}
|
||||
|
||||
}
|
||||
if (readline () == 0) {
|
||||
if (NextLine () == 0) {
|
||||
if (i_ifdef >= 0) {
|
||||
PPError (ERR_CPP_ENDIF_EXPECTED);
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ static int skipwhite (void)
|
||||
{
|
||||
while (1) {
|
||||
while (*lptr == 0) {
|
||||
if (readline () == 0) {
|
||||
if (NextLine () == 0) {
|
||||
return 0;
|
||||
}
|
||||
preprocess ();
|
||||
|
Loading…
x
Reference in New Issue
Block a user