Working on the new backend
git-svn-id: svn://svn.cc65.org/cc65/trunk@700 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
parent
aa6b3afcfc
commit
9d1940a124
16 changed files with 319 additions and 172 deletions
|
@ -36,46 +36,27 @@
|
||||||
/* common */
|
/* common */
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
|
||||||
|
/* b6502 */
|
||||||
|
#include "codeseg.h"
|
||||||
|
#include "dataseg.h"
|
||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "asmline.h"
|
#include "codegen.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "asmcode.h"
|
#include "asmcode.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AddCodeLine (const char* Format, ...)
|
|
||||||
/* Add a new line of code to the output */
|
|
||||||
{
|
|
||||||
va_list ap;
|
|
||||||
va_start (ap, Format);
|
|
||||||
NewCodeLine (Format, ap);
|
|
||||||
va_end (ap);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AddCodeHint (const char* Hint)
|
void AddCodeHint (const char* Hint)
|
||||||
/* Add an optimizer hint */
|
/* Add an optimizer hint */
|
||||||
{
|
{
|
||||||
AddCodeLine ("+%s", Hint);
|
/* ### AddCodeLine ("+%s", Hint); */
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AddEmptyLine (void)
|
|
||||||
/* Add an empty line for formatting purposes */
|
|
||||||
{
|
|
||||||
/* Use a somewhat weird construct to avoid that gcc complains about
|
|
||||||
* an empty format string.
|
|
||||||
*/
|
|
||||||
static const char EmptyLine[] = "";
|
|
||||||
AddCodeLine (EmptyLine);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,10 +64,12 @@ void AddEmptyLine (void)
|
||||||
CodeMark GetCodePos (void)
|
CodeMark GetCodePos (void)
|
||||||
/* Get a marker pointing to the current output position */
|
/* Get a marker pointing to the current output position */
|
||||||
{
|
{
|
||||||
/* This function should never be called without any code output */
|
unsigned EntryCount = GetCodeSegEntries (CS);
|
||||||
CHECK (LastLine != 0);
|
|
||||||
|
|
||||||
return LastLine;
|
/* This function should never be called without any code output */
|
||||||
|
CHECK (EntryCount > 0);
|
||||||
|
|
||||||
|
return EntryCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -94,9 +77,7 @@ CodeMark GetCodePos (void)
|
||||||
void RemoveCode (CodeMark M)
|
void RemoveCode (CodeMark M)
|
||||||
/* Remove all code after the given code marker */
|
/* Remove all code after the given code marker */
|
||||||
{
|
{
|
||||||
while (LastLine != M) {
|
DelCodeSegAfter (CS, M);
|
||||||
FreeCodeLine (LastLine);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -104,18 +85,9 @@ void RemoveCode (CodeMark M)
|
||||||
void WriteOutput (FILE* F)
|
void WriteOutput (FILE* F)
|
||||||
/* Write the final output to a file */
|
/* Write the final output to a file */
|
||||||
{
|
{
|
||||||
Line* L = FirstLine;
|
OutputDataSeg (F, DS);
|
||||||
while (L) {
|
MergeCodeLabels (CS);
|
||||||
/* Don't write optimizer hints if not requested to do so */
|
OutputCodeSeg (F, CS);
|
||||||
if (L->Line[0] == '+') {
|
|
||||||
if (Debug) {
|
|
||||||
fprintf (F, ";%s\n", L->Line);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fprintf (F, "%s\n", L->Line);
|
|
||||||
}
|
|
||||||
L = L->Next;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
|
|
||||||
|
|
||||||
/* Marker for an assembler code position */
|
/* Marker for an assembler code position */
|
||||||
typedef struct Line* CodeMark;
|
typedef unsigned CodeMark;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -62,15 +62,9 @@ typedef struct Line* CodeMark;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AddCodeLine (const char* Format, ...) attribute ((format(printf,1,2)));
|
|
||||||
/* Add a new line of code to the output */
|
|
||||||
|
|
||||||
void AddCodeHint (const char* Hint);
|
void AddCodeHint (const char* Hint);
|
||||||
/* Add an optimizer hint */
|
/* Add an optimizer hint */
|
||||||
|
|
||||||
void AddEmptyLine (void);
|
|
||||||
/* Add an empty line for formatting purposes */
|
|
||||||
|
|
||||||
CodeMark GetCodePos (void);
|
CodeMark GetCodePos (void);
|
||||||
/* Get a marker pointing to the current output position */
|
/* Get a marker pointing to the current output position */
|
||||||
|
|
||||||
|
|
|
@ -34,10 +34,14 @@
|
||||||
|
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
|
#include "check.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* b6502 */
|
/* cc65 */
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
|
/* b6502 */
|
||||||
|
#include "codeinfo.h"
|
||||||
#include "label.h"
|
#include "label.h"
|
||||||
#include "opcodes.h"
|
#include "opcodes.h"
|
||||||
#include "codeent.h"
|
#include "codeent.h"
|
||||||
|
@ -56,7 +60,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM)
|
CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, CodeLabel* JumpTo)
|
||||||
/* Create a new code entry, initialize and return it */
|
/* Create a new code entry, initialize and return it */
|
||||||
{
|
{
|
||||||
/* Allocate memory */
|
/* Allocate memory */
|
||||||
|
@ -69,10 +73,15 @@ CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM)
|
||||||
E->Hints = 0;
|
E->Hints = 0;
|
||||||
E->Arg.Num = 0;
|
E->Arg.Num = 0;
|
||||||
E->Flags = 0;
|
E->Flags = 0;
|
||||||
E->Usage = D->Usage;
|
E->Usage = D->Info & (CI_MASK_USE | CI_MASK_CHG);
|
||||||
E->JumpTo = 0;
|
E->JumpTo = JumpTo;
|
||||||
InitCollection (&E->Labels);
|
InitCollection (&E->Labels);
|
||||||
|
|
||||||
|
/* If we have a label given, add this entry to the label */
|
||||||
|
if (JumpTo) {
|
||||||
|
CollAppend (&JumpTo->JumpFrom, E);
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the initialized struct */
|
/* Return the initialized struct */
|
||||||
return E;
|
return E;
|
||||||
}
|
}
|
||||||
|
@ -115,7 +124,12 @@ void OutputCodeEntry (FILE* F, const CodeEntry* E)
|
||||||
switch (E->AM) {
|
switch (E->AM) {
|
||||||
|
|
||||||
case AM_IMP:
|
case AM_IMP:
|
||||||
/* implicit + accumulator */
|
/* implicit */
|
||||||
|
break;
|
||||||
|
|
||||||
|
case AM_ACC:
|
||||||
|
/* accumulator */
|
||||||
|
fprintf (F, "\ta");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AM_IMM:
|
case AM_IMM:
|
||||||
|
@ -125,8 +139,7 @@ void OutputCodeEntry (FILE* F, const CodeEntry* E)
|
||||||
|
|
||||||
case AM_ZP:
|
case AM_ZP:
|
||||||
case AM_ABS:
|
case AM_ABS:
|
||||||
case AM_BRA:
|
/* zeropage and absolute */
|
||||||
/* zeropage, absolute and branch */
|
|
||||||
fprintf (F, "\t%s", E->Arg.Expr);
|
fprintf (F, "\t%s", E->Arg.Expr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -156,6 +169,12 @@ void OutputCodeEntry (FILE* F, const CodeEntry* E)
|
||||||
fprintf (F, "\t(%s)", E->Arg.Expr);
|
fprintf (F, "\t(%s)", E->Arg.Expr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case AM_BRA:
|
||||||
|
/* branch */
|
||||||
|
CHECK (E->JumpTo != 0);
|
||||||
|
fprintf (F, "\t%s", E->JumpTo->Name);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Internal ("Invalid addressing mode");
|
Internal ("Invalid addressing mode");
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ struct CodeEntry {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM);
|
CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, CodeLabel* JumpTo);
|
||||||
/* Create a new code entry, initialize and return it */
|
/* Create a new code entry, initialize and return it */
|
||||||
|
|
||||||
void FreeCodeEntry (CodeEntry* E);
|
void FreeCodeEntry (CodeEntry* E);
|
||||||
|
|
|
@ -35,11 +35,13 @@
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
/* common */
|
/* common */
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
#include "xsprintf.h"
|
||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "asmcode.h"
|
#include "asmcode.h"
|
||||||
|
@ -48,7 +50,7 @@
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "litpool.h"
|
#include "litpool.h"
|
||||||
#include "optimize.h"
|
/* ### #include "optimize.h" */
|
||||||
#include "segname.h"
|
#include "segname.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "codegen.h"
|
#include "codegen.h"
|
||||||
|
@ -61,17 +63,16 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Compiler relative stk ptr */
|
/* Compiler relative stack pointer */
|
||||||
int oursp = 0;
|
int oursp = 0;
|
||||||
|
|
||||||
|
/* Segments */
|
||||||
|
DataSeg* DS = 0;
|
||||||
|
CodeSeg* CS = 0;
|
||||||
|
|
||||||
/* Current segment */
|
/* Current segment */
|
||||||
segment_t CurSeg = SEG_INV;
|
segment_t CurSeg = SEG_INV;
|
||||||
|
|
||||||
/* Segment names */
|
|
||||||
static char* SegmentHints [4] = {
|
|
||||||
"seg:code", "seg:rodata", "seg:data", "seg:bss"
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
@ -80,6 +81,22 @@ static char* SegmentHints [4] = {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void AddCodeLine (const char* Format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
char Buf [1024];
|
||||||
|
va_start (ap, Format);
|
||||||
|
xvsprintf (Buf, sizeof (Buf), Format, ap);
|
||||||
|
va_end (ap);
|
||||||
|
if (CurSeg == SEG_CODE) {
|
||||||
|
AddCodeSegLine (CS, "%s", Buf);
|
||||||
|
} else {
|
||||||
|
AddDataSegLine (DS, "%s", Buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void typeerror (unsigned type)
|
static void typeerror (unsigned type)
|
||||||
/* Print an error message about an invalid operand type */
|
/* Print an error message about an invalid operand type */
|
||||||
{
|
{
|
||||||
|
@ -108,7 +125,7 @@ static char* GetLabelName (unsigned flags, unsigned long label, unsigned offs)
|
||||||
switch (flags & CF_ADDRMASK) {
|
switch (flags & CF_ADDRMASK) {
|
||||||
|
|
||||||
case CF_STATIC:
|
case CF_STATIC:
|
||||||
/* Static memory cell */
|
/* Static memory cell */
|
||||||
sprintf (lbuf, "L%04X+%u", (unsigned)(label & 0xFFFF), offs);
|
sprintf (lbuf, "L%04X+%u", (unsigned)(label & 0xFFFF), offs);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -146,12 +163,14 @@ static char* GetLabelName (unsigned flags, unsigned long label, unsigned offs)
|
||||||
void g_preamble (void)
|
void g_preamble (void)
|
||||||
/* Generate the assembler code preamble */
|
/* Generate the assembler code preamble */
|
||||||
{
|
{
|
||||||
|
/* ### */
|
||||||
|
CS = NewCodeSeg ("CODE");
|
||||||
|
DS = NewDataSeg ();
|
||||||
|
|
||||||
AddCodeLine ("; File generated by cc65 v %u.%u.%u", VER_MAJOR, VER_MINOR, VER_PATCH);
|
AddCodeLine ("; File generated by cc65 v %u.%u.%u", VER_MAJOR, VER_MINOR, VER_PATCH);
|
||||||
AddEmptyLine ();
|
|
||||||
|
|
||||||
/* Insert some object file options */
|
/* Insert some object file options */
|
||||||
AddCodeLine (".fopt\t\tcompiler,\"cc65 v %u.%u.%u\"", VER_MAJOR, VER_MINOR, VER_PATCH);
|
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 we're producing code for some other CPU, switch the command set */
|
||||||
if (CPU == CPU_65C02) {
|
if (CPU == CPU_65C02) {
|
||||||
|
@ -172,14 +191,6 @@ void g_preamble (void)
|
||||||
|
|
||||||
/* Define long branch macros */
|
/* Define long branch macros */
|
||||||
AddCodeLine (".macpack\tlongbranch");
|
AddCodeLine (".macpack\tlongbranch");
|
||||||
AddEmptyLine ();
|
|
||||||
|
|
||||||
/* Define the ldax macro */
|
|
||||||
AddCodeLine (".macro ldax Value");
|
|
||||||
AddCodeLine (" lda #<(Value)");
|
|
||||||
AddCodeLine (" ldx #>(Value)");
|
|
||||||
AddCodeLine (".endmacro");
|
|
||||||
AddEmptyLine ();
|
|
||||||
|
|
||||||
/* Tell the optimizer that this is the end of the preamble */
|
/* Tell the optimizer that this is the end of the preamble */
|
||||||
AddCodeHint ("end_of_preamble");
|
AddCodeHint ("end_of_preamble");
|
||||||
|
@ -207,8 +218,9 @@ static void UseSeg (int NewSeg)
|
||||||
{
|
{
|
||||||
if (CurSeg != NewSeg) {
|
if (CurSeg != NewSeg) {
|
||||||
CurSeg = (segment_t) NewSeg;
|
CurSeg = (segment_t) NewSeg;
|
||||||
AddCodeLine (".segment\t\"%s\"", SegmentNames [CurSeg]);
|
if (CurSeg != SEG_CODE) {
|
||||||
AddCodeHint (SegmentHints [CurSeg]);
|
AddCodeLine (".segment\t\"%s\"", SegmentNames [CurSeg]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,7 +390,11 @@ static unsigned MakeByteOffs (unsigned Flags, unsigned Offs)
|
||||||
void g_defloclabel (unsigned label)
|
void g_defloclabel (unsigned label)
|
||||||
/* Define a local label */
|
/* Define a local label */
|
||||||
{
|
{
|
||||||
AddCodeLine ("L%04X:", label & 0xFFFF);
|
if (CurSeg == SEG_CODE) {
|
||||||
|
AddCodeSegLabel (CS, LocalLabelName (label));
|
||||||
|
} else {
|
||||||
|
AddDataSegLine (DS, "%s:", LocalLabelName (label));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -392,7 +408,14 @@ void g_defloclabel (unsigned label)
|
||||||
void g_defgloblabel (const char* Name)
|
void g_defgloblabel (const char* Name)
|
||||||
/* Define a global label with the given name */
|
/* Define a global label with the given name */
|
||||||
{
|
{
|
||||||
AddCodeLine ("_%s:", Name);
|
if (CurSeg == SEG_CODE) {
|
||||||
|
/* ##### */
|
||||||
|
char Buf[64];
|
||||||
|
xsprintf (Buf, sizeof (Buf), "_%s", Name);
|
||||||
|
AddCodeSegLabel (CS, Buf);
|
||||||
|
} else {
|
||||||
|
AddDataSegLine (DS, "_%s:", Name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -401,9 +424,9 @@ void g_defexport (const char* Name, int ZP)
|
||||||
/* Export the given label */
|
/* Export the given label */
|
||||||
{
|
{
|
||||||
if (ZP) {
|
if (ZP) {
|
||||||
AddCodeLine ("\t.exportzp\t_%s", Name);
|
AddDataSegLine (DS, "\t.exportzp\t_%s", Name);
|
||||||
} else {
|
} else {
|
||||||
AddCodeLine ("\t.export\t\t_%s", Name);
|
AddDataSegLine (DS, "\t.export\t\t_%s", Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,9 +436,9 @@ void g_defimport (const char* Name, int ZP)
|
||||||
/* Import the given label */
|
/* Import the given label */
|
||||||
{
|
{
|
||||||
if (ZP) {
|
if (ZP) {
|
||||||
AddCodeLine ("\t.importzp\t_%s", Name);
|
AddDataSegLine (DS, "\t.importzp\t_%s", Name);
|
||||||
} else {
|
} else {
|
||||||
AddCodeLine ("\t.import\t\t_%s", Name);
|
AddDataSegLine (DS, "\t.import\t\t_%s", Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -550,9 +573,6 @@ void g_leave (int flags, int val)
|
||||||
/* Output the jump */
|
/* Output the jump */
|
||||||
AddCodeLine (buf);
|
AddCodeLine (buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add an empty line after a function to make the code more readable */
|
|
||||||
AddEmptyLine ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -716,7 +736,8 @@ void g_getimmed (unsigned flags, unsigned long val, unsigned offs)
|
||||||
const char* Label = GetLabelName (flags, val, offs);
|
const char* Label = GetLabelName (flags, val, offs);
|
||||||
|
|
||||||
/* Load the address into the primary */
|
/* Load the address into the primary */
|
||||||
AddCodeLine ("\tldax\t%s", Label);
|
AddCodeLine ("\tlda\t#<(%s)", Label);
|
||||||
|
AddCodeLine ("\tldx\t#>(%s)", Label);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998 Ullrich von Bassewitz */
|
/* (C) 1998-2001 llrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Wacholderweg 14 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70597 Stuttgart */
|
||||||
/* EMail: uz@musoftware.de */
|
/* EMail: uz@musoftware.de */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
|
@ -37,6 +37,12 @@
|
||||||
#define CODEGEN_H
|
#define CODEGEN_H
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* ##### */
|
||||||
|
#include "dataseg.h"
|
||||||
|
#include "codeseg.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* data */
|
/* data */
|
||||||
|
@ -80,6 +86,10 @@
|
||||||
/* Compiler relative stackpointer */
|
/* Compiler relative stackpointer */
|
||||||
extern int oursp;
|
extern int oursp;
|
||||||
|
|
||||||
|
/* Segments */
|
||||||
|
extern DataSeg* DS;
|
||||||
|
extern CodeSeg* CS;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
|
@ -55,13 +55,16 @@
|
||||||
#define CI_USE_A 0x0001U /* Use the A register */
|
#define CI_USE_A 0x0001U /* Use the A register */
|
||||||
#define CI_USE_X 0x0002U /* Use the X register */
|
#define CI_USE_X 0x0002U /* Use the X register */
|
||||||
#define CI_USE_Y 0x0004U /* Use the Y register */
|
#define CI_USE_Y 0x0004U /* Use the Y register */
|
||||||
#define CI_MASK_USE 0x00FFU /* Extract usage info */
|
#define CI_MASK_USE 0x000FU /* Extract usage info */
|
||||||
|
|
||||||
#define CI_CHG_NONE 0x0000U /* Change nothing */
|
#define CI_CHG_NONE 0x0000U /* Change nothing */
|
||||||
#define CI_CHG_A 0x0100U /* Change the A register */
|
#define CI_CHG_A 0x0010U /* Change the A register */
|
||||||
#define CI_CHG_X 0x0200U /* Change the X register */
|
#define CI_CHG_X 0x0020U /* Change the X register */
|
||||||
#define CI_CHG_Y 0x0400U /* Change the Y register */
|
#define CI_CHG_Y 0x0040U /* Change the Y register */
|
||||||
#define CI_MASK_CHG 0xFF00U /* Extract change info */
|
#define CI_MASK_CHG 0x00F0U /* Extract change info */
|
||||||
|
|
||||||
|
#define CI_BRA 0x0100U /* Instruction is a branch */
|
||||||
|
#define CI_MASK_BRA 0x0100U /* Extract branch info */
|
||||||
|
|
||||||
#define CI_NONE 0x0000U /* Nothing used/changed */
|
#define CI_NONE 0x0000U /* Nothing used/changed */
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@
|
||||||
|
|
||||||
/* b6502 */
|
/* b6502 */
|
||||||
#include "codeent.h"
|
#include "codeent.h"
|
||||||
|
#include "codeinfo.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "codeseg.h"
|
#include "codeseg.h"
|
||||||
|
|
||||||
|
@ -57,6 +58,22 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static CodeLabel* NewCodeSegLabel (CodeSeg* S, const char* Name, unsigned Hash)
|
||||||
|
/* Create a new label and insert it into the label hash table */
|
||||||
|
{
|
||||||
|
/* Not found - create a new one */
|
||||||
|
CodeLabel* L = NewCodeLabel (Name, Hash);
|
||||||
|
|
||||||
|
/* Enter the label into the hash table */
|
||||||
|
L->Next = S->LabelHash[L->Hash];
|
||||||
|
S->LabelHash[L->Hash] = L;
|
||||||
|
|
||||||
|
/* Return the new label */
|
||||||
|
return L;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const char* SkipSpace (const char* S)
|
static const char* SkipSpace (const char* S)
|
||||||
/* Skip white space and return an updated pointer */
|
/* Skip white space and return an updated pointer */
|
||||||
{
|
{
|
||||||
|
@ -98,7 +115,7 @@ static const char* ReadToken (const char* L, const char* Term,
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static CodeEntry* ParseInsn (const char* L)
|
static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
|
||||||
/* Parse an instruction nnd generate a code entry from it. If the line contains
|
/* Parse an instruction nnd generate a code entry from it. If the line contains
|
||||||
* errors, output an error message and return NULL.
|
* errors, output an error message and return NULL.
|
||||||
* For simplicity, we don't accept the broad range of input a "real" assembler
|
* For simplicity, we don't accept the broad range of input a "real" assembler
|
||||||
|
@ -112,6 +129,7 @@ static CodeEntry* ParseInsn (const char* L)
|
||||||
char Expr[64];
|
char Expr[64];
|
||||||
char Reg;
|
char Reg;
|
||||||
CodeEntry* E;
|
CodeEntry* E;
|
||||||
|
CodeLabel* Label;
|
||||||
|
|
||||||
/* Mnemonic */
|
/* Mnemonic */
|
||||||
L = ReadToken (L, " \t", Mnemo, sizeof (Mnemo));
|
L = ReadToken (L, " \t", Mnemo, sizeof (Mnemo));
|
||||||
|
@ -132,6 +150,11 @@ static CodeEntry* ParseInsn (const char* L)
|
||||||
Expr[0] = '\0';
|
Expr[0] = '\0';
|
||||||
switch (*L) {
|
switch (*L) {
|
||||||
|
|
||||||
|
case '\0':
|
||||||
|
/* Implicit */
|
||||||
|
AM = AM_IMP;
|
||||||
|
break;
|
||||||
|
|
||||||
case '#':
|
case '#':
|
||||||
/* Immidiate */
|
/* Immidiate */
|
||||||
StrCopy (Expr, sizeof (Expr), L+1);
|
StrCopy (Expr, sizeof (Expr), L+1);
|
||||||
|
@ -195,7 +218,7 @@ static CodeEntry* ParseInsn (const char* L)
|
||||||
case 'A':
|
case 'A':
|
||||||
/* Accumulator? */
|
/* Accumulator? */
|
||||||
if (L[1] == '\0') {
|
if (L[1] == '\0') {
|
||||||
AM = AM_IMP;
|
AM = AM_ACC;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* FALLTHROUGH */
|
/* FALLTHROUGH */
|
||||||
|
@ -216,27 +239,46 @@ static CodeEntry* ParseInsn (const char* L)
|
||||||
Reg = toupper (*L);
|
Reg = toupper (*L);
|
||||||
L = SkipSpace (L+1);
|
L = SkipSpace (L+1);
|
||||||
if (Reg == 'X') {
|
if (Reg == 'X') {
|
||||||
AM = AM_ABSX;
|
AM = AM_ABSX;
|
||||||
} else if (Reg == 'Y') {
|
} else if (Reg == 'Y') {
|
||||||
AM = AM_ABSY;
|
AM = AM_ABSY;
|
||||||
} else {
|
} else {
|
||||||
Error ("ASM code error: syntax error");
|
Error ("ASM code error: syntax error");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (*L != '\0') {
|
if (*L != '\0') {
|
||||||
Error ("ASM code error: syntax error");
|
Error ("ASM code error: syntax error");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the instruction is a branch, check for the label and generate it
|
||||||
|
* if it does not exist.
|
||||||
|
*/
|
||||||
|
Label = 0;
|
||||||
|
if ((OPC->Info & CI_MASK_BRA) == CI_BRA) {
|
||||||
|
|
||||||
|
unsigned Hash;
|
||||||
|
|
||||||
|
/* ### Check for local labels here */
|
||||||
|
CHECK (AM == AM_ABS);
|
||||||
|
AM = AM_BRA;
|
||||||
|
Hash = HashStr (Expr) % CS_LABEL_HASH_SIZE;
|
||||||
|
Label = FindCodeLabel (S, Expr, Hash);
|
||||||
|
if (Label == 0) {
|
||||||
|
/* Generate a new label */
|
||||||
|
Label = NewCodeSegLabel (S, Expr, Hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* We do now have the addressing mode in AM. Allocate a new CodeEntry
|
/* We do now have the addressing mode in AM. Allocate a new CodeEntry
|
||||||
* structure and initialize it.
|
* structure and initialize it.
|
||||||
*/
|
*/
|
||||||
E = NewCodeEntry (OPC, AM);
|
E = NewCodeEntry (OPC, AM, Label);
|
||||||
if (Expr[0] != '\0') {
|
if (Expr[0] != '\0') {
|
||||||
/* We have an additional expression */
|
/* We have an additional expression */
|
||||||
E->Arg.Expr = xstrdup (Expr);
|
E->Arg.Expr = xstrdup (Expr);
|
||||||
|
@ -309,6 +351,7 @@ void AddCodeSegLine (CodeSeg* S, const char* Format, ...)
|
||||||
{
|
{
|
||||||
const char* L;
|
const char* L;
|
||||||
CodeEntry* E;
|
CodeEntry* E;
|
||||||
|
char Token[64];
|
||||||
|
|
||||||
/* Format the line */
|
/* Format the line */
|
||||||
va_list ap;
|
va_list ap;
|
||||||
|
@ -334,11 +377,12 @@ void AddCodeSegLine (CodeSeg* S, const char* Format, ...)
|
||||||
|
|
||||||
case '.':
|
case '.':
|
||||||
/* Control instruction */
|
/* Control instruction */
|
||||||
Error ("ASM code error: Pseudo instructions not supported");
|
ReadToken (L, " \t", Token, sizeof (Token));
|
||||||
|
Error ("ASM code error: Pseudo instruction `%s' not supported", Token);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
E = ParseInsn (L);
|
E = ParseInsn (S, L);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,11 +420,7 @@ void AddCodeSegLabel (CodeSeg* S, const char* Name)
|
||||||
CHECK (L->Owner == 0);
|
CHECK (L->Owner == 0);
|
||||||
} else {
|
} else {
|
||||||
/* Not found - create a new one */
|
/* Not found - create a new one */
|
||||||
L = NewCodeLabel (Name, Hash);
|
L = NewCodeSegLabel (S, Name, Hash);
|
||||||
|
|
||||||
/* Enter the label into the hash table */
|
|
||||||
L->Next = S->LabelHash[L->Hash];
|
|
||||||
S->LabelHash[L->Hash] = L;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We do now have a valid label. Remember it for later */
|
/* We do now have a valid label. Remember it for later */
|
||||||
|
@ -389,6 +429,48 @@ void AddCodeSegLabel (CodeSeg* S, const char* Name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void AddCodeSegHint (CodeSeg* S, unsigned Hint)
|
||||||
|
/* Add a hint for the preceeding instruction */
|
||||||
|
{
|
||||||
|
CodeEntry* E;
|
||||||
|
|
||||||
|
/* Get the number of entries in this segment */
|
||||||
|
unsigned EntryCount = CollCount (&S->Entries);
|
||||||
|
|
||||||
|
/* Must have at least one entry */
|
||||||
|
CHECK (EntryCount > 0);
|
||||||
|
|
||||||
|
/* Get the last entry */
|
||||||
|
E = CollAt (&S->Entries, EntryCount-1);
|
||||||
|
|
||||||
|
/* Add the hint */
|
||||||
|
E->Hints |= Hint;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void DelCodeSegAfter (CodeSeg* S, unsigned Last)
|
||||||
|
/* Delete all entries after the given one */
|
||||||
|
{
|
||||||
|
unsigned I;
|
||||||
|
|
||||||
|
/* Get the number of entries in this segment */
|
||||||
|
unsigned Count = CollCount (&S->Entries);
|
||||||
|
|
||||||
|
/* ### We need some more cleanup here wrt labels */
|
||||||
|
|
||||||
|
/* Remove all entries after the given one */
|
||||||
|
for (I = Count-1; I > Last; --I) {
|
||||||
|
FreeCodeEntry (CollAt (&S->Entries, I));
|
||||||
|
CollDelete (&S->Entries, I);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete all waiting labels */
|
||||||
|
CollDeleteAll (&S->Labels);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void OutputCodeSeg (FILE* F, const CodeSeg* S)
|
void OutputCodeSeg (FILE* F, const CodeSeg* S)
|
||||||
/* Output the code segment data to a file */
|
/* Output the code segment data to a file */
|
||||||
{
|
{
|
||||||
|
@ -397,6 +479,9 @@ void OutputCodeSeg (FILE* F, const CodeSeg* S)
|
||||||
/* Get the number of entries in this segment */
|
/* Get the number of entries in this segment */
|
||||||
unsigned Count = CollCount (&S->Entries);
|
unsigned Count = CollCount (&S->Entries);
|
||||||
|
|
||||||
|
/* Output the segment directive */
|
||||||
|
fprintf (F, ".segment\t\"%s\"\n", S->Name);
|
||||||
|
|
||||||
/* Output all entries */
|
/* Output all entries */
|
||||||
for (I = 0; I < Count; ++I) {
|
for (I = 0; I < Count; ++I) {
|
||||||
OutputCodeEntry (F, CollConstAt (&S->Entries, I));
|
OutputCodeEntry (F, CollConstAt (&S->Entries, I));
|
||||||
|
@ -441,13 +526,17 @@ void MergeCodeLabels (CodeSeg* S)
|
||||||
/* Get a pointer to the next entry */
|
/* Get a pointer to the next entry */
|
||||||
CodeEntry* E = CollAt (&S->Entries, I);
|
CodeEntry* E = CollAt (&S->Entries, I);
|
||||||
|
|
||||||
/* If this entry has one or zero labels, continue with the next one */
|
/* If this entry has zero labels, continue with the next one */
|
||||||
unsigned LabelCount = CollCount (&E->Labels);
|
unsigned LabelCount = CollCount (&E->Labels);
|
||||||
if (LabelCount <= 1) {
|
if (LabelCount == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have more than one label. Use the first one as reference label */
|
/* We have at least one label. Use the first one as reference label.
|
||||||
|
* We don't have a notification for global labels for now, and using
|
||||||
|
* the first one will also keep the global function labels, since these
|
||||||
|
* are inserted at position 0.
|
||||||
|
*/
|
||||||
RefLab = CollAt (&E->Labels, 0);
|
RefLab = CollAt (&E->Labels, 0);
|
||||||
|
|
||||||
/* Walk through the remaining labels and change references to these
|
/* Walk through the remaining labels and change references to these
|
||||||
|
@ -466,13 +555,13 @@ void MergeCodeLabels (CodeSeg* S)
|
||||||
unsigned RefCount = CollCount (&L->JumpFrom);
|
unsigned RefCount = CollCount (&L->JumpFrom);
|
||||||
for (K = 0; K < RefCount; ++K) {
|
for (K = 0; K < RefCount; ++K) {
|
||||||
|
|
||||||
/* Get the next instrcuction that references this label */
|
/* Get the next instrcuction that references this label */
|
||||||
CodeEntry* E = CollAt (&L->JumpFrom, K);
|
CodeEntry* E = CollAt (&L->JumpFrom, K);
|
||||||
|
|
||||||
/* Change the reference */
|
/* Change the reference */
|
||||||
CHECK (E->JumpTo == L);
|
CHECK (E->JumpTo == L);
|
||||||
E->JumpTo = RefLab;
|
E->JumpTo = RefLab;
|
||||||
CollAppend (&RefLab->JumpFrom, E);
|
CollAppend (&RefLab->JumpFrom, E);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -483,8 +572,28 @@ void MergeCodeLabels (CodeSeg* S)
|
||||||
CollDelete (&E->Labels, J);
|
CollDelete (&E->Labels, J);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The reference label is the only remaining label. Check if there
|
||||||
|
* are any references to this label, and delete it if this is not
|
||||||
|
* the case.
|
||||||
|
*/
|
||||||
|
if (CollCount (&RefLab->JumpFrom) == 0) {
|
||||||
|
/* Delete the label */
|
||||||
|
FreeCodeLabel (RefLab);
|
||||||
|
/* Remove it from the list */
|
||||||
|
CollDelete (&E->Labels, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned GetCodeSegEntries (const CodeSeg* S)
|
||||||
|
/* Return the number of entries for the given code segment */
|
||||||
|
{
|
||||||
|
return CollCount (&S->Entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,7 @@ struct CodeSeg {
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,6 +87,12 @@ void AddCodeSegLine (CodeSeg* S, const char* Format, ...) attribute ((format(pri
|
||||||
void AddCodeSegLabel (CodeSeg* S, const char* Name);
|
void AddCodeSegLabel (CodeSeg* S, const char* Name);
|
||||||
/* Add a label for the next instruction to follow */
|
/* Add a label for the next instruction to follow */
|
||||||
|
|
||||||
|
void AddCodeSegHint (CodeSeg* S, unsigned Hint);
|
||||||
|
/* Add a hint for the preceeding instruction */
|
||||||
|
|
||||||
|
void DelCodeSegAfter (CodeSeg* S, unsigned Last);
|
||||||
|
/* Delete all entries after the given one */
|
||||||
|
|
||||||
void OutputCodeSeg (FILE* F, const CodeSeg* S);
|
void OutputCodeSeg (FILE* F, const CodeSeg* S);
|
||||||
/* Output the code segment data to a file */
|
/* Output the code segment data to a file */
|
||||||
|
|
||||||
|
@ -98,6 +104,9 @@ void MergeCodeLabels (CodeSeg* S);
|
||||||
* one and adjust the code entries accordingly.
|
* one and adjust the code entries accordingly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
unsigned GetCodeSegEntries (const CodeSeg* S);
|
||||||
|
/* Return the number of entries for the given code segment */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of codeseg.h */
|
/* End of codeseg.h */
|
||||||
|
|
|
@ -744,7 +744,11 @@ void doasm (void)
|
||||||
* looks like the one defined for C++ (C has no ASM directive), that is,
|
* looks like the one defined for C++ (C has no ASM directive), that is,
|
||||||
* a string literal in parenthesis.
|
* a string literal in parenthesis.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
|
/* ########## */
|
||||||
|
Error ("Currently unavailable");
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Skip the ASM */
|
/* Skip the ASM */
|
||||||
NextToken ();
|
NextToken ();
|
||||||
|
|
||||||
|
@ -771,6 +775,7 @@ void doasm (void)
|
||||||
|
|
||||||
/* Closing paren needed */
|
/* Closing paren needed */
|
||||||
ConsumeRParen ();
|
ConsumeRParen ();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -378,13 +378,16 @@ int NextLine (void)
|
||||||
--Len;
|
--Len;
|
||||||
}
|
}
|
||||||
line [Len] = '\0';
|
line [Len] = '\0';
|
||||||
|
|
||||||
/* Output the source line in the generated assembler file
|
#if 0
|
||||||
* if requested.
|
/* ######### */
|
||||||
*/
|
/* Output the source line in the generated assembler file
|
||||||
if (AddSource && line[Start] != '\0') {
|
* if requested.
|
||||||
AddCodeLine ("; %s", line+Start);
|
*/
|
||||||
}
|
if (AddSource && line[Start] != '\0') {
|
||||||
|
AddCodeLine ("; %s", line+Start);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Check if we have a line continuation character at the end. If not,
|
/* Check if we have a line continuation character at the end. If not,
|
||||||
* we're done.
|
* we're done.
|
||||||
|
|
|
@ -58,7 +58,7 @@
|
||||||
#include "incpath.h"
|
#include "incpath.h"
|
||||||
#include "input.h"
|
#include "input.h"
|
||||||
#include "macrotab.h"
|
#include "macrotab.h"
|
||||||
#include "optimize.h"
|
/* #include "optimize.h" */
|
||||||
#include "scanner.h"
|
#include "scanner.h"
|
||||||
#include "segname.h"
|
#include "segname.h"
|
||||||
|
|
||||||
|
@ -567,10 +567,12 @@ int main (int argc, char* argv[])
|
||||||
Optimize = 1;
|
Optimize = 1;
|
||||||
P = Arg + 2;
|
P = Arg + 2;
|
||||||
while (*P) {
|
while (*P) {
|
||||||
switch (*P++) {
|
switch (*P++) {
|
||||||
case 'f':
|
#if 0
|
||||||
sscanf (P, "%lx", (long*) &OptDisable);
|
case 'f':
|
||||||
|
sscanf (P, "%lx", (long*) &OptDisable);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
case 'i':
|
case 'i':
|
||||||
FavourSize = 0;
|
FavourSize = 0;
|
||||||
CodeSizeFactor = 200;
|
CodeSizeFactor = 200;
|
||||||
|
@ -637,10 +639,12 @@ int main (int argc, char* argv[])
|
||||||
|
|
||||||
FILE* F;
|
FILE* F;
|
||||||
|
|
||||||
/* Optimize the output if requested */
|
#if 0
|
||||||
if (Optimize) {
|
/* Optimize the output if requested */
|
||||||
OptDoOpt ();
|
if (Optimize) {
|
||||||
}
|
OptDoOpt ();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Open the file */
|
/* Open the file */
|
||||||
F = fopen (OutputFile, "w");
|
F = fopen (OutputFile, "w");
|
||||||
|
|
|
@ -26,7 +26,6 @@ LDFLAGS=
|
||||||
OBJS = anonname.o \
|
OBJS = anonname.o \
|
||||||
asmcode.o \
|
asmcode.o \
|
||||||
asmlabel.o \
|
asmlabel.o \
|
||||||
asmline.o \
|
|
||||||
codegen.o \
|
codegen.o \
|
||||||
compile.o \
|
compile.o \
|
||||||
cpu.o \
|
cpu.o \
|
||||||
|
@ -49,7 +48,6 @@ OBJS = anonname.o \
|
||||||
loop.o \
|
loop.o \
|
||||||
macrotab.o \
|
macrotab.o \
|
||||||
main.o \
|
main.o \
|
||||||
optimize.o \
|
|
||||||
preproc.o \
|
preproc.o \
|
||||||
pragma.o \
|
pragma.o \
|
||||||
scanner.o \
|
scanner.o \
|
||||||
|
@ -61,8 +59,8 @@ OBJS = anonname.o \
|
||||||
typecmp.o \
|
typecmp.o \
|
||||||
util.o
|
util.o
|
||||||
|
|
||||||
LIBS = $(COMMON)/common.a \
|
LIBS = $(B6502)/b6502.a \
|
||||||
$(B6502)/b6502.a
|
$(COMMON)/common.a
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
|
@ -57,17 +57,17 @@ static const OPCDesc OPCTable[OPC_COUNT] = {
|
||||||
{ "adc", OPC_ADC, CI_USE_A | CI_CHG_A },
|
{ "adc", OPC_ADC, CI_USE_A | CI_CHG_A },
|
||||||
{ "and", OPC_AND, CI_USE_A | CI_CHG_A },
|
{ "and", OPC_AND, CI_USE_A | CI_CHG_A },
|
||||||
{ "asl", OPC_ASL, CI_USE_A | CI_CHG_A },
|
{ "asl", OPC_ASL, CI_USE_A | CI_CHG_A },
|
||||||
{ "bcc", OPC_BCC, CI_CHG_NONE },
|
{ "bcc", OPC_BCC, CI_BRA },
|
||||||
{ "bcs", OPC_BCS, CI_CHG_NONE },
|
{ "bcs", OPC_BCS, CI_BRA },
|
||||||
{ "beq", OPC_BEQ, CI_CHG_NONE },
|
{ "beq", OPC_BEQ, CI_BRA },
|
||||||
{ "bit", OPC_BIT, CI_USE_A },
|
{ "bit", OPC_BIT, CI_USE_A },
|
||||||
{ "bmi", OPC_BMI, CI_CHG_NONE },
|
{ "bmi", OPC_BMI, CI_BRA },
|
||||||
{ "bne", OPC_BNE, CI_CHG_NONE },
|
{ "bne", OPC_BNE, CI_BRA },
|
||||||
{ "bpl", OPC_BPL, CI_CHG_NONE },
|
{ "bpl", OPC_BPL, CI_BRA },
|
||||||
{ "bra", OPC_BRA, CI_CHG_NONE },
|
{ "bra", OPC_BRA, CI_BRA },
|
||||||
{ "brk", OPC_BRK, CI_CHG_NONE },
|
{ "brk", OPC_BRK, CI_BRA },
|
||||||
{ "bvc", OPC_BVC, CI_CHG_NONE },
|
{ "bvc", OPC_BVC, CI_BRA },
|
||||||
{ "bvs", OPC_BVS, CI_CHG_NONE },
|
{ "bvs", OPC_BVS, CI_BRA },
|
||||||
{ "clc", OPC_CLC, CI_CHG_NONE },
|
{ "clc", OPC_CLC, CI_CHG_NONE },
|
||||||
{ "cld", OPC_CLD, CI_CHG_NONE },
|
{ "cld", OPC_CLD, CI_CHG_NONE },
|
||||||
{ "cli", OPC_CLI, CI_CHG_NONE },
|
{ "cli", OPC_CLI, CI_CHG_NONE },
|
||||||
|
@ -84,8 +84,8 @@ static const OPCDesc OPCTable[OPC_COUNT] = {
|
||||||
{ "inc", OPC_INC, CI_NONE },
|
{ "inc", OPC_INC, CI_NONE },
|
||||||
{ "inx", OPC_INX, CI_USE_X | CI_CHG_X },
|
{ "inx", OPC_INX, CI_USE_X | CI_CHG_X },
|
||||||
{ "iny", OPC_INY, CI_USE_Y | CI_CHG_Y },
|
{ "iny", OPC_INY, CI_USE_Y | CI_CHG_Y },
|
||||||
{ "jmp", OPC_JMP, CI_NONE },
|
{ "jmp", OPC_JMP, CI_BRA },
|
||||||
{ "jsr", OPC_JSR, CI_NONE },
|
{ "jsr", OPC_JSR, CI_BRA },
|
||||||
{ "lda", OPC_LDA, CI_CHG_A },
|
{ "lda", OPC_LDA, CI_CHG_A },
|
||||||
{ "ldx", OPC_LDX, CI_CHG_X },
|
{ "ldx", OPC_LDX, CI_CHG_X },
|
||||||
{ "ldy", OPC_LDY, CI_CHG_Y },
|
{ "ldy", OPC_LDY, CI_CHG_Y },
|
||||||
|
@ -173,6 +173,7 @@ unsigned GetInsnSize (opc_t OPC, am_t AM)
|
||||||
*/
|
*/
|
||||||
switch (AM) {
|
switch (AM) {
|
||||||
case AM_IMP: return 1;
|
case AM_IMP: return 1;
|
||||||
|
case AM_ACC: return 1;
|
||||||
case AM_IMM: return 2;
|
case AM_IMM: return 2;
|
||||||
case AM_ZP: return 2;
|
case AM_ZP: return 2;
|
||||||
case AM_ZPX: return 2;
|
case AM_ZPX: return 2;
|
||||||
|
@ -201,4 +202,4 @@ const OPCDesc* GetOPCDesc (opc_t OPC)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -116,24 +116,25 @@ typedef enum {
|
||||||
|
|
||||||
/* Addressing modes (bitmapped). */
|
/* Addressing modes (bitmapped). */
|
||||||
typedef enum {
|
typedef enum {
|
||||||
AM_IMP = 0x0001, /* implicit + accumulator */
|
AM_IMP = 0x0001, /* implicit */
|
||||||
AM_IMM = 0x0002, /* immidiate */
|
AM_ACC = 0x0002, /* accumulator */
|
||||||
AM_ZP = 0x0004, /* zeropage */
|
AM_IMM = 0x0004, /* immidiate */
|
||||||
AM_ZPX = 0x0008, /* zeropage,X */
|
AM_ZP = 0x0008, /* zeropage */
|
||||||
AM_ABS = 0x0010, /* absolute */
|
AM_ZPX = 0x0010, /* zeropage,X */
|
||||||
AM_ABSX = 0x0020, /* absolute,X */
|
AM_ABS = 0x0020, /* absolute */
|
||||||
AM_ABSY = 0x0040, /* absolute,Y */
|
AM_ABSX = 0x0040, /* absolute,X */
|
||||||
AM_ZPX_IND = 0x0080, /* (zeropage,x) */
|
AM_ABSY = 0x0080, /* absolute,Y */
|
||||||
AM_ZP_INDY = 0x0100, /* (zeropage),y */
|
AM_ZPX_IND = 0x0100, /* (zeropage,x) */
|
||||||
AM_ZP_IND = 0x0200, /* (zeropage) */
|
AM_ZP_INDY = 0x0200, /* (zeropage),y */
|
||||||
AM_BRA = 0x0400 /* branch */
|
AM_ZP_IND = 0x0400, /* (zeropage) */
|
||||||
|
AM_BRA = 0x0800 /* branch */
|
||||||
} am_t;
|
} am_t;
|
||||||
|
|
||||||
/* Opcode description */
|
/* Opcode description */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char Mnemo[4]; /* Mnemonic */
|
char Mnemo[4]; /* Mnemonic */
|
||||||
opc_t OPC; /* Opcode */
|
opc_t OPC; /* Opcode */
|
||||||
unsigned Usage; /* Usage flags */
|
unsigned Info; /* Usage flags */
|
||||||
} OPCDesc;
|
} OPCDesc;
|
||||||
|
|
||||||
|
|
||||||
|
@ -154,7 +155,7 @@ unsigned GetInsnSize (opc_t OPC, am_t AM);
|
||||||
|
|
||||||
const OPCDesc* GetOPCDesc (opc_t OPC);
|
const OPCDesc* GetOPCDesc (opc_t OPC);
|
||||||
/* Get an opcode description */
|
/* Get an opcode description */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of opcodes.h */
|
/* End of opcodes.h */
|
||||||
|
|
|
@ -820,8 +820,6 @@ void EmitExternals (void)
|
||||||
{
|
{
|
||||||
SymEntry* Entry;
|
SymEntry* Entry;
|
||||||
|
|
||||||
AddEmptyLine ();
|
|
||||||
|
|
||||||
Entry = SymTab->SymHead;
|
Entry = SymTab->SymHead;
|
||||||
while (Entry) {
|
while (Entry) {
|
||||||
unsigned Flags = Entry->Flags;
|
unsigned Flags = Entry->Flags;
|
||||||
|
|
Loading…
Add table
Reference in a new issue