mirror of
https://github.com/cc65/cc65.git
synced 2024-12-28 06:30:16 +00:00
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
@ -36,46 +36,27 @@
|
||||
/* common */
|
||||
#include "check.h"
|
||||
|
||||
/* b6502 */
|
||||
#include "codeseg.h"
|
||||
#include "dataseg.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "asmline.h"
|
||||
#include "codegen.h"
|
||||
#include "global.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)
|
||||
/* Add an optimizer 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);
|
||||
/* ### AddCodeLine ("+%s", Hint); */
|
||||
}
|
||||
|
||||
|
||||
@ -83,10 +64,12 @@ void AddEmptyLine (void)
|
||||
CodeMark GetCodePos (void)
|
||||
/* Get a marker pointing to the current output position */
|
||||
{
|
||||
/* This function should never be called without any code output */
|
||||
CHECK (LastLine != 0);
|
||||
unsigned EntryCount = GetCodeSegEntries (CS);
|
||||
|
||||
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)
|
||||
/* Remove all code after the given code marker */
|
||||
{
|
||||
while (LastLine != M) {
|
||||
FreeCodeLine (LastLine);
|
||||
}
|
||||
DelCodeSegAfter (CS, M);
|
||||
}
|
||||
|
||||
|
||||
@ -104,18 +85,9 @@ void RemoveCode (CodeMark M)
|
||||
void WriteOutput (FILE* F)
|
||||
/* Write the final output to a file */
|
||||
{
|
||||
Line* L = FirstLine;
|
||||
while (L) {
|
||||
/* Don't write optimizer hints if not requested to do so */
|
||||
if (L->Line[0] == '+') {
|
||||
if (Debug) {
|
||||
fprintf (F, ";%s\n", L->Line);
|
||||
}
|
||||
} else {
|
||||
fprintf (F, "%s\n", L->Line);
|
||||
}
|
||||
L = L->Next;
|
||||
}
|
||||
OutputDataSeg (F, DS);
|
||||
MergeCodeLabels (CS);
|
||||
OutputCodeSeg (F, CS);
|
||||
}
|
||||
|
||||
|
||||
|
@ -52,7 +52,7 @@
|
||||
|
||||
|
||||
/* 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);
|
||||
/* Add an optimizer hint */
|
||||
|
||||
void AddEmptyLine (void);
|
||||
/* Add an empty line for formatting purposes */
|
||||
|
||||
CodeMark GetCodePos (void);
|
||||
/* Get a marker pointing to the current output position */
|
||||
|
||||
|
@ -34,10 +34,14 @@
|
||||
|
||||
|
||||
/* common */
|
||||
#include "check.h"
|
||||
#include "xmalloc.h"
|
||||
|
||||
/* b6502 */
|
||||
/* cc65 */
|
||||
#include "error.h"
|
||||
|
||||
/* b6502 */
|
||||
#include "codeinfo.h"
|
||||
#include "label.h"
|
||||
#include "opcodes.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 */
|
||||
{
|
||||
/* Allocate memory */
|
||||
@ -69,10 +73,15 @@ CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM)
|
||||
E->Hints = 0;
|
||||
E->Arg.Num = 0;
|
||||
E->Flags = 0;
|
||||
E->Usage = D->Usage;
|
||||
E->JumpTo = 0;
|
||||
E->Usage = D->Info & (CI_MASK_USE | CI_MASK_CHG);
|
||||
E->JumpTo = JumpTo;
|
||||
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 E;
|
||||
}
|
||||
@ -115,7 +124,12 @@ void OutputCodeEntry (FILE* F, const CodeEntry* E)
|
||||
switch (E->AM) {
|
||||
|
||||
case AM_IMP:
|
||||
/* implicit + accumulator */
|
||||
/* implicit */
|
||||
break;
|
||||
|
||||
case AM_ACC:
|
||||
/* accumulator */
|
||||
fprintf (F, "\ta");
|
||||
break;
|
||||
|
||||
case AM_IMM:
|
||||
@ -125,8 +139,7 @@ void OutputCodeEntry (FILE* F, const CodeEntry* E)
|
||||
|
||||
case AM_ZP:
|
||||
case AM_ABS:
|
||||
case AM_BRA:
|
||||
/* zeropage, absolute and branch */
|
||||
/* zeropage and absolute */
|
||||
fprintf (F, "\t%s", E->Arg.Expr);
|
||||
break;
|
||||
|
||||
@ -156,6 +169,12 @@ void OutputCodeEntry (FILE* F, const CodeEntry* E)
|
||||
fprintf (F, "\t(%s)", E->Arg.Expr);
|
||||
break;
|
||||
|
||||
case AM_BRA:
|
||||
/* branch */
|
||||
CHECK (E->JumpTo != 0);
|
||||
fprintf (F, "\t%s", E->JumpTo->Name);
|
||||
break;
|
||||
|
||||
default:
|
||||
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 */
|
||||
|
||||
void FreeCodeEntry (CodeEntry* E);
|
||||
|
@ -35,11 +35,13 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* common */
|
||||
#include "check.h"
|
||||
#include "version.h"
|
||||
#include "xmalloc.h"
|
||||
#include "xsprintf.h"
|
||||
|
||||
/* cc65 */
|
||||
#include "asmcode.h"
|
||||
@ -48,7 +50,7 @@
|
||||
#include "error.h"
|
||||
#include "global.h"
|
||||
#include "litpool.h"
|
||||
#include "optimize.h"
|
||||
/* ### #include "optimize.h" */
|
||||
#include "segname.h"
|
||||
#include "util.h"
|
||||
#include "codegen.h"
|
||||
@ -61,17 +63,16 @@
|
||||
|
||||
|
||||
|
||||
/* Compiler relative stk ptr */
|
||||
/* Compiler relative stack pointer */
|
||||
int oursp = 0;
|
||||
|
||||
/* Segments */
|
||||
DataSeg* DS = 0;
|
||||
CodeSeg* CS = 0;
|
||||
|
||||
/* Current segment */
|
||||
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)
|
||||
/* 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) {
|
||||
|
||||
case CF_STATIC:
|
||||
/* Static memory cell */
|
||||
/* Static memory cell */
|
||||
sprintf (lbuf, "L%04X+%u", (unsigned)(label & 0xFFFF), offs);
|
||||
break;
|
||||
|
||||
@ -146,12 +163,14 @@ static char* GetLabelName (unsigned flags, unsigned long label, unsigned offs)
|
||||
void g_preamble (void)
|
||||
/* 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);
|
||||
AddEmptyLine ();
|
||||
|
||||
/* Insert some object file options */
|
||||
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) {
|
||||
@ -172,14 +191,6 @@ void g_preamble (void)
|
||||
|
||||
/* Define long branch macros */
|
||||
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 */
|
||||
AddCodeHint ("end_of_preamble");
|
||||
@ -207,8 +218,9 @@ static void UseSeg (int NewSeg)
|
||||
{
|
||||
if (CurSeg != NewSeg) {
|
||||
CurSeg = (segment_t) NewSeg;
|
||||
AddCodeLine (".segment\t\"%s\"", SegmentNames [CurSeg]);
|
||||
AddCodeHint (SegmentHints [CurSeg]);
|
||||
if (CurSeg != SEG_CODE) {
|
||||
AddCodeLine (".segment\t\"%s\"", SegmentNames [CurSeg]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -378,7 +390,11 @@ static unsigned MakeByteOffs (unsigned Flags, unsigned Offs)
|
||||
void g_defloclabel (unsigned 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)
|
||||
/* 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 */
|
||||
{
|
||||
if (ZP) {
|
||||
AddCodeLine ("\t.exportzp\t_%s", Name);
|
||||
AddDataSegLine (DS, "\t.exportzp\t_%s", Name);
|
||||
} 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 */
|
||||
{
|
||||
if (ZP) {
|
||||
AddCodeLine ("\t.importzp\t_%s", Name);
|
||||
AddDataSegLine (DS, "\t.importzp\t_%s", Name);
|
||||
} 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 */
|
||||
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);
|
||||
|
||||
/* 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 */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* (C) 1998-2001 llrich von Bassewitz */
|
||||
/* Wacholderweg 14 */
|
||||
/* D-70597 Stuttgart */
|
||||
/* EMail: uz@musoftware.de */
|
||||
/* */
|
||||
/* */
|
||||
/* This software is provided 'as-is', without any expressed or implied */
|
||||
@ -37,6 +37,12 @@
|
||||
#define CODEGEN_H
|
||||
|
||||
|
||||
|
||||
/* ##### */
|
||||
#include "dataseg.h"
|
||||
#include "codeseg.h"
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* data */
|
||||
@ -80,6 +86,10 @@
|
||||
/* Compiler relative stackpointer */
|
||||
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_X 0x0002U /* Use the X 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_A 0x0100U /* Change the A register */
|
||||
#define CI_CHG_X 0x0200U /* Change the X register */
|
||||
#define CI_CHG_Y 0x0400U /* Change the Y register */
|
||||
#define CI_MASK_CHG 0xFF00U /* Extract change info */
|
||||
#define CI_CHG_A 0x0010U /* Change the A register */
|
||||
#define CI_CHG_X 0x0020U /* Change the X register */
|
||||
#define CI_CHG_Y 0x0040U /* Change the Y register */
|
||||
#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 */
|
||||
|
||||
|
@ -46,6 +46,7 @@
|
||||
|
||||
/* b6502 */
|
||||
#include "codeent.h"
|
||||
#include "codeinfo.h"
|
||||
#include "error.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)
|
||||
/* 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
|
||||
* errors, output an error message and return NULL.
|
||||
* 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 Reg;
|
||||
CodeEntry* E;
|
||||
CodeLabel* Label;
|
||||
|
||||
/* Mnemonic */
|
||||
L = ReadToken (L, " \t", Mnemo, sizeof (Mnemo));
|
||||
@ -132,6 +150,11 @@ static CodeEntry* ParseInsn (const char* L)
|
||||
Expr[0] = '\0';
|
||||
switch (*L) {
|
||||
|
||||
case '\0':
|
||||
/* Implicit */
|
||||
AM = AM_IMP;
|
||||
break;
|
||||
|
||||
case '#':
|
||||
/* Immidiate */
|
||||
StrCopy (Expr, sizeof (Expr), L+1);
|
||||
@ -195,7 +218,7 @@ static CodeEntry* ParseInsn (const char* L)
|
||||
case 'A':
|
||||
/* Accumulator? */
|
||||
if (L[1] == '\0') {
|
||||
AM = AM_IMP;
|
||||
AM = AM_ACC;
|
||||
break;
|
||||
}
|
||||
/* FALLTHROUGH */
|
||||
@ -216,27 +239,46 @@ static CodeEntry* ParseInsn (const char* L)
|
||||
Reg = toupper (*L);
|
||||
L = SkipSpace (L+1);
|
||||
if (Reg == 'X') {
|
||||
AM = AM_ABSX;
|
||||
AM = AM_ABSX;
|
||||
} else if (Reg == 'Y') {
|
||||
AM = AM_ABSY;
|
||||
AM = AM_ABSY;
|
||||
} else {
|
||||
Error ("ASM code error: syntax error");
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
if (*L != '\0') {
|
||||
Error ("ASM code error: syntax error");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
Error ("ASM code error: syntax error");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
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
|
||||
* structure and initialize it.
|
||||
*/
|
||||
E = NewCodeEntry (OPC, AM);
|
||||
E = NewCodeEntry (OPC, AM, Label);
|
||||
if (Expr[0] != '\0') {
|
||||
/* We have an additional expression */
|
||||
E->Arg.Expr = xstrdup (Expr);
|
||||
@ -309,6 +351,7 @@ void AddCodeSegLine (CodeSeg* S, const char* Format, ...)
|
||||
{
|
||||
const char* L;
|
||||
CodeEntry* E;
|
||||
char Token[64];
|
||||
|
||||
/* Format the line */
|
||||
va_list ap;
|
||||
@ -334,11 +377,12 @@ void AddCodeSegLine (CodeSeg* S, const char* Format, ...)
|
||||
|
||||
case '.':
|
||||
/* 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;
|
||||
|
||||
default:
|
||||
E = ParseInsn (L);
|
||||
E = ParseInsn (S, L);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -376,11 +420,7 @@ void AddCodeSegLabel (CodeSeg* S, const char* Name)
|
||||
CHECK (L->Owner == 0);
|
||||
} else {
|
||||
/* Not found - create a new one */
|
||||
L = NewCodeLabel (Name, Hash);
|
||||
|
||||
/* Enter the label into the hash table */
|
||||
L->Next = S->LabelHash[L->Hash];
|
||||
S->LabelHash[L->Hash] = L;
|
||||
L = NewCodeSegLabel (S, Name, Hash);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
/* 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 */
|
||||
unsigned Count = CollCount (&S->Entries);
|
||||
|
||||
/* Output the segment directive */
|
||||
fprintf (F, ".segment\t\"%s\"\n", S->Name);
|
||||
|
||||
/* Output all entries */
|
||||
for (I = 0; I < Count; ++I) {
|
||||
OutputCodeEntry (F, CollConstAt (&S->Entries, I));
|
||||
@ -441,13 +526,17 @@ void MergeCodeLabels (CodeSeg* S)
|
||||
/* Get a pointer to the next entry */
|
||||
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);
|
||||
if (LabelCount <= 1) {
|
||||
if (LabelCount == 0) {
|
||||
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);
|
||||
|
||||
/* Walk through the remaining labels and change references to these
|
||||
@ -466,13 +555,13 @@ void MergeCodeLabels (CodeSeg* S)
|
||||
unsigned RefCount = CollCount (&L->JumpFrom);
|
||||
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);
|
||||
|
||||
/* Change the reference */
|
||||
CHECK (E->JumpTo == L);
|
||||
E->JumpTo = RefLab;
|
||||
CollAppend (&RefLab->JumpFrom, E);
|
||||
/* Change the reference */
|
||||
CHECK (E->JumpTo == L);
|
||||
E->JumpTo = RefLab;
|
||||
CollAppend (&RefLab->JumpFrom, E);
|
||||
|
||||
}
|
||||
|
||||
@ -483,8 +572,28 @@ void MergeCodeLabels (CodeSeg* S)
|
||||
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);
|
||||
/* 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);
|
||||
/* Output the code segment data to a file */
|
||||
|
||||
@ -98,6 +104,9 @@ void MergeCodeLabels (CodeSeg* S);
|
||||
* 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 */
|
||||
|
@ -744,7 +744,11 @@ void doasm (void)
|
||||
* looks like the one defined for C++ (C has no ASM directive), that is,
|
||||
* a string literal in parenthesis.
|
||||
*/
|
||||
{
|
||||
{
|
||||
/* ########## */
|
||||
Error ("Currently unavailable");
|
||||
|
||||
#if 0
|
||||
/* Skip the ASM */
|
||||
NextToken ();
|
||||
|
||||
@ -771,6 +775,7 @@ void doasm (void)
|
||||
|
||||
/* Closing paren needed */
|
||||
ConsumeRParen ();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -378,13 +378,16 @@ int NextLine (void)
|
||||
--Len;
|
||||
}
|
||||
line [Len] = '\0';
|
||||
|
||||
/* Output the source line in the generated assembler file
|
||||
* if requested.
|
||||
*/
|
||||
if (AddSource && line[Start] != '\0') {
|
||||
AddCodeLine ("; %s", line+Start);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* ######### */
|
||||
/* Output the source line in the generated assembler file
|
||||
* if requested.
|
||||
*/
|
||||
if (AddSource && line[Start] != '\0') {
|
||||
AddCodeLine ("; %s", line+Start);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check if we have a line continuation character at the end. If not,
|
||||
* we're done.
|
||||
|
@ -58,7 +58,7 @@
|
||||
#include "incpath.h"
|
||||
#include "input.h"
|
||||
#include "macrotab.h"
|
||||
#include "optimize.h"
|
||||
/* #include "optimize.h" */
|
||||
#include "scanner.h"
|
||||
#include "segname.h"
|
||||
|
||||
@ -567,10 +567,12 @@ int main (int argc, char* argv[])
|
||||
Optimize = 1;
|
||||
P = Arg + 2;
|
||||
while (*P) {
|
||||
switch (*P++) {
|
||||
case 'f':
|
||||
sscanf (P, "%lx", (long*) &OptDisable);
|
||||
switch (*P++) {
|
||||
#if 0
|
||||
case 'f':
|
||||
sscanf (P, "%lx", (long*) &OptDisable);
|
||||
break;
|
||||
#endif
|
||||
case 'i':
|
||||
FavourSize = 0;
|
||||
CodeSizeFactor = 200;
|
||||
@ -637,10 +639,12 @@ int main (int argc, char* argv[])
|
||||
|
||||
FILE* F;
|
||||
|
||||
/* Optimize the output if requested */
|
||||
if (Optimize) {
|
||||
OptDoOpt ();
|
||||
}
|
||||
#if 0
|
||||
/* Optimize the output if requested */
|
||||
if (Optimize) {
|
||||
OptDoOpt ();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Open the file */
|
||||
F = fopen (OutputFile, "w");
|
||||
|
@ -26,7 +26,6 @@ LDFLAGS=
|
||||
OBJS = anonname.o \
|
||||
asmcode.o \
|
||||
asmlabel.o \
|
||||
asmline.o \
|
||||
codegen.o \
|
||||
compile.o \
|
||||
cpu.o \
|
||||
@ -49,7 +48,6 @@ OBJS = anonname.o \
|
||||
loop.o \
|
||||
macrotab.o \
|
||||
main.o \
|
||||
optimize.o \
|
||||
preproc.o \
|
||||
pragma.o \
|
||||
scanner.o \
|
||||
@ -61,8 +59,8 @@ OBJS = anonname.o \
|
||||
typecmp.o \
|
||||
util.o
|
||||
|
||||
LIBS = $(COMMON)/common.a \
|
||||
$(B6502)/b6502.a
|
||||
LIBS = $(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 },
|
||||
{ "and", OPC_AND, CI_USE_A | CI_CHG_A },
|
||||
{ "asl", OPC_ASL, CI_USE_A | CI_CHG_A },
|
||||
{ "bcc", OPC_BCC, CI_CHG_NONE },
|
||||
{ "bcs", OPC_BCS, CI_CHG_NONE },
|
||||
{ "beq", OPC_BEQ, CI_CHG_NONE },
|
||||
{ "bcc", OPC_BCC, CI_BRA },
|
||||
{ "bcs", OPC_BCS, CI_BRA },
|
||||
{ "beq", OPC_BEQ, CI_BRA },
|
||||
{ "bit", OPC_BIT, CI_USE_A },
|
||||
{ "bmi", OPC_BMI, CI_CHG_NONE },
|
||||
{ "bne", OPC_BNE, CI_CHG_NONE },
|
||||
{ "bpl", OPC_BPL, CI_CHG_NONE },
|
||||
{ "bra", OPC_BRA, CI_CHG_NONE },
|
||||
{ "brk", OPC_BRK, CI_CHG_NONE },
|
||||
{ "bvc", OPC_BVC, CI_CHG_NONE },
|
||||
{ "bvs", OPC_BVS, CI_CHG_NONE },
|
||||
{ "bmi", OPC_BMI, CI_BRA },
|
||||
{ "bne", OPC_BNE, CI_BRA },
|
||||
{ "bpl", OPC_BPL, CI_BRA },
|
||||
{ "bra", OPC_BRA, CI_BRA },
|
||||
{ "brk", OPC_BRK, CI_BRA },
|
||||
{ "bvc", OPC_BVC, CI_BRA },
|
||||
{ "bvs", OPC_BVS, CI_BRA },
|
||||
{ "clc", OPC_CLC, CI_CHG_NONE },
|
||||
{ "cld", OPC_CLD, CI_CHG_NONE },
|
||||
{ "cli", OPC_CLI, CI_CHG_NONE },
|
||||
@ -84,8 +84,8 @@ static const OPCDesc OPCTable[OPC_COUNT] = {
|
||||
{ "inc", OPC_INC, CI_NONE },
|
||||
{ "inx", OPC_INX, CI_USE_X | CI_CHG_X },
|
||||
{ "iny", OPC_INY, CI_USE_Y | CI_CHG_Y },
|
||||
{ "jmp", OPC_JMP, CI_NONE },
|
||||
{ "jsr", OPC_JSR, CI_NONE },
|
||||
{ "jmp", OPC_JMP, CI_BRA },
|
||||
{ "jsr", OPC_JSR, CI_BRA },
|
||||
{ "lda", OPC_LDA, CI_CHG_A },
|
||||
{ "ldx", OPC_LDX, CI_CHG_X },
|
||||
{ "ldy", OPC_LDY, CI_CHG_Y },
|
||||
@ -173,6 +173,7 @@ unsigned GetInsnSize (opc_t OPC, am_t AM)
|
||||
*/
|
||||
switch (AM) {
|
||||
case AM_IMP: return 1;
|
||||
case AM_ACC: return 1;
|
||||
case AM_IMM: return 2;
|
||||
case AM_ZP: 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). */
|
||||
typedef enum {
|
||||
AM_IMP = 0x0001, /* implicit + accumulator */
|
||||
AM_IMM = 0x0002, /* immidiate */
|
||||
AM_ZP = 0x0004, /* zeropage */
|
||||
AM_ZPX = 0x0008, /* zeropage,X */
|
||||
AM_ABS = 0x0010, /* absolute */
|
||||
AM_ABSX = 0x0020, /* absolute,X */
|
||||
AM_ABSY = 0x0040, /* absolute,Y */
|
||||
AM_ZPX_IND = 0x0080, /* (zeropage,x) */
|
||||
AM_ZP_INDY = 0x0100, /* (zeropage),y */
|
||||
AM_ZP_IND = 0x0200, /* (zeropage) */
|
||||
AM_BRA = 0x0400 /* branch */
|
||||
AM_IMP = 0x0001, /* implicit */
|
||||
AM_ACC = 0x0002, /* accumulator */
|
||||
AM_IMM = 0x0004, /* immidiate */
|
||||
AM_ZP = 0x0008, /* zeropage */
|
||||
AM_ZPX = 0x0010, /* zeropage,X */
|
||||
AM_ABS = 0x0020, /* absolute */
|
||||
AM_ABSX = 0x0040, /* absolute,X */
|
||||
AM_ABSY = 0x0080, /* absolute,Y */
|
||||
AM_ZPX_IND = 0x0100, /* (zeropage,x) */
|
||||
AM_ZP_INDY = 0x0200, /* (zeropage),y */
|
||||
AM_ZP_IND = 0x0400, /* (zeropage) */
|
||||
AM_BRA = 0x0800 /* branch */
|
||||
} am_t;
|
||||
|
||||
/* Opcode description */
|
||||
typedef struct {
|
||||
char Mnemo[4]; /* Mnemonic */
|
||||
opc_t OPC; /* Opcode */
|
||||
unsigned Usage; /* Usage flags */
|
||||
unsigned Info; /* Usage flags */
|
||||
} OPCDesc;
|
||||
|
||||
|
||||
@ -154,7 +155,7 @@ unsigned GetInsnSize (opc_t OPC, am_t AM);
|
||||
|
||||
const OPCDesc* GetOPCDesc (opc_t OPC);
|
||||
/* Get an opcode description */
|
||||
|
||||
|
||||
|
||||
|
||||
/* End of opcodes.h */
|
||||
|
@ -820,8 +820,6 @@ void EmitExternals (void)
|
||||
{
|
||||
SymEntry* Entry;
|
||||
|
||||
AddEmptyLine ();
|
||||
|
||||
Entry = SymTab->SymHead;
|
||||
while (Entry) {
|
||||
unsigned Flags = Entry->Flags;
|
||||
|
Loading…
Reference in New Issue
Block a user