1
0
mirror of https://github.com/cc65/cc65.git synced 2025-04-06 20:37:16 +00:00

Working on the backend

git-svn-id: svn://svn.cc65.org/cc65/trunk@699 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2001-04-30 20:00:13 +00:00
parent ddc60c20fe
commit aa6b3afcfc
12 changed files with 1742 additions and 22 deletions

170
src/cc65/codeent.c Normal file
View File

@ -0,0 +1,170 @@
/*****************************************************************************/
/* */
/* codeent.c */
/* */
/* Code segment entry */
/* */
/* */
/* */
/* (C) 2001 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. */
/* */
/*****************************************************************************/
/* common */
#include "xmalloc.h"
/* b6502 */
#include "error.h"
#include "label.h"
#include "opcodes.h"
#include "codeent.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/*****************************************************************************/
/* Code */
/*****************************************************************************/
CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM)
/* Create a new code entry, initialize and return it */
{
/* Allocate memory */
CodeEntry* E = xmalloc (sizeof (CodeEntry));
/* Initialize the fields */
E->OPC = D->OPC;
E->AM = AM;
E->Size = GetInsnSize (E->OPC, E->AM);
E->Hints = 0;
E->Arg.Num = 0;
E->Flags = 0;
E->Usage = D->Usage;
E->JumpTo = 0;
InitCollection (&E->Labels);
/* Return the initialized struct */
return E;
}
void FreeCodeEntry (CodeEntry* E)
/* Free the given code entry */
{
/* ## Free the string argument if we have one */
/* Cleanup the collection */
DoneCollection (&E->Labels);
/* Free the entry */
xfree (E);
}
void OutputCodeEntry (FILE* F, const CodeEntry* E)
/* Output the code entry to a file */
{
const OPCDesc* D;
/* If we have a label, print that */
unsigned LabelCount = CollCount (&E->Labels);
unsigned I;
for (I = 0; I < LabelCount; ++I) {
OutputCodeLabel (F, CollConstAt (&E->Labels, I));
}
/* Get the opcode description */
D = GetOPCDesc (E->OPC);
/* Print the mnemonic */
fprintf (F, "\t%s", D->Mnemo);
/* Print the operand */
switch (E->AM) {
case AM_IMP:
/* implicit + accumulator */
break;
case AM_IMM:
/* immidiate */
fprintf (F, "\t#%s", E->Arg.Expr);
break;
case AM_ZP:
case AM_ABS:
case AM_BRA:
/* zeropage, absolute and branch */
fprintf (F, "\t%s", E->Arg.Expr);
break;
case AM_ZPX:
case AM_ABSX:
/* zeropage,X and absolute,X */
fprintf (F, "\t%s,x", E->Arg.Expr);
break;
case AM_ABSY:
/* absolute,Y */
fprintf (F, "\t%s,y", E->Arg.Expr);
break;
case AM_ZPX_IND:
/* (zeropage,x) */
fprintf (F, "\t(%s,x)", E->Arg.Expr);
break;
case AM_ZP_INDY:
/* (zeropage),y */
fprintf (F, "\t(%s),y", E->Arg.Expr);
break;
case AM_ZP_IND:
/* (zeropage) */
fprintf (F, "\t(%s)", E->Arg.Expr);
break;
default:
Internal ("Invalid addressing mode");
}
/* Terminate the line */
fprintf (F, "\n");
}

98
src/cc65/codeent.h Normal file
View File

@ -0,0 +1,98 @@
/*****************************************************************************/
/* */
/* codeent.h */
/* */
/* Code segment entry */
/* */
/* */
/* */
/* (C) 2001 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 CODEENT_H
#define CODEENT_H
#include <stdio.h>
/* common */
#include "coll.h"
/* b6502 */
#include "label.h"
#include "opcodes.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Code entry structure */
typedef struct CodeEntry CodeEntry;
struct CodeEntry {
opc_t OPC; /* Opcode */
am_t AM; /* Adressing mode */
unsigned char Size; /* Estimated size */
unsigned char Hints; /* Hints for this entry */
union {
unsigned Num; /* Numeric argument */
char* Expr; /* Textual argument */
} Arg;
unsigned short Flags; /* Flags */
unsigned short Usage; /* Register usage for this entry */
CodeLabel* JumpTo; /* Jump label */
Collection Labels; /* Labels for this instruction */
};
/*****************************************************************************/
/* Code */
/*****************************************************************************/
CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM);
/* Create a new code entry, initialize and return it */
void FreeCodeEntry (CodeEntry* E);
/* Free the given code entry */
void OutputCodeEntry (FILE* F, const CodeEntry* E);
/* Output the code entry to a file */
/* End of codeent.h */
#endif

80
src/cc65/codeinfo.h Normal file
View File

@ -0,0 +1,80 @@
/*****************************************************************************/
/* */
/* codeinfo.h */
/* */
/* Additional information about code instructions */
/* */
/* */
/* */
/* (C) 2001 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 CODEINFO_H
#define CODEINFO_H
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Flags that tell what a specific instruction does with a register.
* Please note that *changing* a register must not necessarily mean that the
* value currently in the register is used. A prominent example is a load
* instruction: It changes the register contents and does not use the old
* value. On the flip side, a shift or something similar would use the
* current value and change it.
*/
#define CI_USE_NONE 0x0000U /* Use nothing */
#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_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_NONE 0x0000U /* Nothing used/changed */
/*****************************************************************************/
/* Code */
/*****************************************************************************/
/* End of codeinfo.h */
#endif

91
src/cc65/codelab.c Normal file
View File

@ -0,0 +1,91 @@
/*****************************************************************************/
/* */
/* label.c */
/* */
/* Code label structure */
/* */
/* */
/* */
/* (C) 2001 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. */
/* */
/*****************************************************************************/
/* common */
#include "xmalloc.h"
/* cc65 */
#include "label.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
CodeLabel* NewCodeLabel (const char* Name, unsigned Hash)
/* Create a new code label, initialize and return it */
{
/* Allocate memory */
CodeLabel* L = xmalloc (sizeof (CodeLabel));
/* Initialize the fields */
L->Next = 0;
L->Name = xstrdup (Name);
L->Hash = Hash;
L->Owner = 0;
InitCollection (&L->JumpFrom);
/* Return the new label */
return L;
}
void FreeCodeLabel (CodeLabel* L)
/* Free the given code label */
{
/* Free the name */
xfree (L->Name);
/* Free the collection */
DoneCollection (&L->JumpFrom);
/* Delete the struct */
xfree (L);
}
void OutputCodeLabel (FILE* F, const CodeLabel* L)
/* Output the code label to a file */
{
fprintf (F, "%s:\n", L->Name);
}

87
src/cc65/codelab.h Normal file
View File

@ -0,0 +1,87 @@
/*****************************************************************************/
/* */
/* label.h */
/* */
/* Code label structure */
/* */
/* */
/* */
/* (C) 2001 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 LABEL_H
#define LABEL_H
#include <stdio.h>
/* common */
#include "coll.h"
/*****************************************************************************/
/* struct CodeLabel */
/*****************************************************************************/
/* Label structure */
typedef struct CodeLabel CodeLabel;
struct CodeLabel {
CodeLabel* Next; /* Next in hash list */
char* Name; /* Label name */
unsigned Hash; /* Hash over the name */
struct CodeEntry* Owner; /* Owner entry */
Collection JumpFrom; /* Entries that jump here */
};
/*****************************************************************************/
/* Code */
/*****************************************************************************/
CodeLabel* NewCodeLabel (const char* Name, unsigned Hash);
/* Create a new code label, initialize and return it */
void FreeCodeLabel (CodeLabel* L);
/* Free the given code label */
void OutputCodeLabel (FILE* F, const CodeLabel* L);
/* Output the code label to a file */
/* End of label.h */
#endif

490
src/cc65/codeseg.c Normal file
View File

@ -0,0 +1,490 @@
/*****************************************************************************/
/* */
/* codeseg.c */
/* */
/* Code segment structure */
/* */
/* */
/* */
/* (C) 2001 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 <string.h>
#include <ctype.h>
/* common */
#include "chartype.h"
#include "check.h"
#include "hashstr.h"
#include "strutil.h"
#include "xmalloc.h"
#include "xsprintf.h"
/* b6502 */
#include "codeent.h"
#include "error.h"
#include "codeseg.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
static const char* SkipSpace (const char* S)
/* Skip white space and return an updated pointer */
{
while (IsSpace (*S)) {
++S;
}
return S;
}
static const char* ReadToken (const char* L, const char* Term,
char* Buf, unsigned BufSize)
/* Read the next token into Buf, return the updated line pointer. The
* token is terminated by one of the characters given in term.
*/
{
/* Read/copy the token */
unsigned I = 0;
unsigned ParenCount = 0;
while (*L && (ParenCount > 0 || strchr (Term, *L) == 0)) {
if (I < BufSize-1) {
Buf[I++] = *L;
}
if (*L == ')') {
--ParenCount;
} else if (*L == '(') {
++ParenCount;
}
++L;
}
/* Terminate the buffer contents */
Buf[I] = '\0';
/* Return the updated line pointer */
return L;
}
static CodeEntry* ParseInsn (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
* does. The instruction and the argument are expected to be separated by
* white space, for example.
*/
{
char Mnemo[16];
const OPCDesc* OPC;
am_t AM = 0; /* Initialize to keep gcc silent */
char Expr[64];
char Reg;
CodeEntry* E;
/* Mnemonic */
L = ReadToken (L, " \t", Mnemo, sizeof (Mnemo));
/* Try to find the opcode description for the mnemonic */
OPC = FindOpcode (Mnemo);
/* If we didn't find the opcode, print an error and bail out */
if (OPC == 0) {
Error ("ASM code error: %s is not a valid mnemonic", Mnemo);
return 0;
}
/* Skip separator white space */
L = SkipSpace (L);
/* Get the addressing mode */
Expr[0] = '\0';
switch (*L) {
case '#':
/* Immidiate */
StrCopy (Expr, sizeof (Expr), L+1);
AM = AM_IMM;
break;
case '(':
/* Indirect */
L = ReadToken (L+1, ",)", Expr, sizeof (Expr));
/* Check for errors */
if (*L == '\0') {
Error ("ASM code error: syntax error");
return 0;
}
/* Check the different indirect modes */
if (*L == ',') {
/* Expect zp x indirect */
L = SkipSpace (L+1);
if (toupper (*L) != 'X') {
Error ("ASM code error: `X' expected");
return 0;
}
L = SkipSpace (L+1);
if (*L != ')') {
Error ("ASM code error: `)' expected");
return 0;
}
L = SkipSpace (L+1);
if (*L != '\0') {
Error ("ASM code error: syntax error");
return 0;
}
AM = AM_ZPX_IND;
} else if (*L == ')') {
/* zp indirect or zp indirect, y */
L = SkipSpace (L+1);
if (*L == ',') {
L = SkipSpace (L+1);
if (toupper (*L) != 'Y') {
Error ("ASM code error: `Y' expected");
return 0;
}
L = SkipSpace (L+1);
if (*L != '\0') {
Error ("ASM code error: syntax error");
return 0;
}
AM = AM_ZP_INDY;
} else if (*L == '\0') {
AM = AM_ZP_IND;
} else {
Error ("ASM code error: syntax error");
return 0;
}
}
break;
case 'a':
case 'A':
/* Accumulator? */
if (L[1] == '\0') {
AM = AM_IMP;
break;
}
/* FALLTHROUGH */
default:
/* Absolute, maybe indexed */
L = ReadToken (L, ",", Expr, sizeof (Expr));
if (*L == '\0') {
/* Assume absolute */
AM = AM_ABS;
} else if (*L == ',') {
/* Indexed */
L = SkipSpace (L+1);
if (*L == '\0') {
Error ("ASM code error: syntax error");
return 0;
} else {
Reg = toupper (*L);
L = SkipSpace (L+1);
if (Reg == 'X') {
AM = AM_ABSX;
} else if (Reg == 'Y') {
AM = AM_ABSY;
} else {
Error ("ASM code error: syntax error");
return 0;
}
if (*L != '\0') {
Error ("ASM code error: syntax error");
return 0;
}
}
}
break;
}
/* We do now have the addressing mode in AM. Allocate a new CodeEntry
* structure and initialize it.
*/
E = NewCodeEntry (OPC, AM);
if (Expr[0] != '\0') {
/* We have an additional expression */
E->Arg.Expr = xstrdup (Expr);
}
/* Return the new code entry */
return E;
}
CodeSeg* NewCodeSeg (const char* Name)
/* Create a new code segment, initialize and return it */
{
unsigned I;
/* Allocate memory */
CodeSeg* S = xmalloc (sizeof (CodeSeg));
/* Initialize the fields */
S->Name = xstrdup (Name);
InitCollection (&S->Entries);
InitCollection (&S->Labels);
for (I = 0; I < sizeof(S->LabelHash) / sizeof(S->LabelHash[0]); ++I) {
S->LabelHash[I] = 0;
}
/* Return the new struct */
return S;
}
void FreeCodeSeg (CodeSeg* S)
/* Free a code segment including all code entries */
{
unsigned I, Count;
/* Free the name */
xfree (S->Name);
/* Free the entries */
Count = CollCount (&S->Entries);
for (I = 0; I < Count; ++I) {
FreeCodeEntry (CollAt (&S->Entries, I));
}
/* Free the collections */
DoneCollection (&S->Entries);
DoneCollection (&S->Labels);
/* Free all labels */
for (I = 0; I < sizeof(S->LabelHash) / sizeof(S->LabelHash[0]); ++I) {
CodeLabel* L = S->LabelHash[I];
while (L) {
CodeLabel* Tmp = L;
L = L->Next;
FreeCodeLabel (Tmp);
}
}
/* Free the struct */
xfree (S);
}
void AddCodeSegLine (CodeSeg* S, const char* Format, ...)
/* Add a line to the given code segment */
{
const char* L;
CodeEntry* E;
/* Format the line */
va_list ap;
char Buf [256];
va_start (ap, Format);
xvsprintf (Buf, sizeof (Buf), Format, ap);
va_end (ap);
/* Skip whitespace */
L = SkipSpace (Buf);
/* Check which type of instruction we have */
E = 0; /* Assume no insn created */
switch (*L) {
case '\0':
/* Empty line, just ignore it */
break;
case ';':
/* Comment or hint, ignore it for now */
break;
case '.':
/* Control instruction */
Error ("ASM code error: Pseudo instructions not supported");
break;
default:
E = ParseInsn (L);
break;
}
/* If we have a code entry, transfer the labels and insert it */
if (E) {
/* Transfer the labels if we have any */
unsigned LabelCount = CollCount (&S->Labels);
unsigned I;
for (I = 0; I < LabelCount; ++I) {
CollAppend (&E->Labels, CollAt (&S->Labels, I));
}
CollDeleteAll (&S->Labels);
/* Add the entry to the list of code entries in this segment */
CollAppend (&S->Entries, E);
}
}
void AddCodeSegLabel (CodeSeg* S, const char* Name)
/* Add a label for the next instruction to follow */
{
/* Calculate the hash from the name */
unsigned Hash = HashStr (Name) % CS_LABEL_HASH_SIZE;
/* Try to find the code label if it does already exist */
CodeLabel* L = FindCodeLabel (S, Name, Hash);
/* Did we find it? */
if (L) {
/* We found it - be sure it does not already have an owner */
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;
}
/* We do now have a valid label. Remember it for later */
CollAppend (&S->Labels, L);
}
void OutputCodeSeg (FILE* F, const CodeSeg* S)
/* Output the code segment data to a file */
{
unsigned I;
/* Get the number of entries in this segment */
unsigned Count = CollCount (&S->Entries);
/* Output all entries */
for (I = 0; I < Count; ++I) {
OutputCodeEntry (F, CollConstAt (&S->Entries, I));
}
}
CodeLabel* FindCodeLabel (CodeSeg* S, const char* Name, unsigned Hash)
/* Find the label with the given name. Return the label or NULL if not found */
{
/* Get the first hash chain entry */
CodeLabel* L = S->LabelHash[Hash];
/* Search the list */
while (L) {
if (strcmp (Name, L->Name) == 0) {
/* Found */
break;
}
L = L->Next;
}
return L;
}
void MergeCodeLabels (CodeSeg* S)
/* Merge code labels. That means: For each instruction, remove all labels but
* one and adjust the code entries accordingly.
*/
{
unsigned I;
/* Walk over all code entries */
unsigned EntryCount = CollCount (&S->Entries);
for (I = 0; I < EntryCount; ++I) {
CodeLabel* RefLab;
unsigned J;
/* 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 */
unsigned LabelCount = CollCount (&E->Labels);
if (LabelCount <= 1) {
continue;
}
/* We have more than one label. Use the first one as reference label */
RefLab = CollAt (&E->Labels, 0);
/* Walk through the remaining labels and change references to these
* labels to a reference to the one and only label. Delete the labels
* that are no longer used. To increase performance, walk backwards
* through the list.
*/
for (J = LabelCount-1; J >= 1; --J) {
unsigned K;
/* Get the next label */
CodeLabel* L = CollAt (&E->Labels, J);
/* Walk through all instructions referencing this label */
unsigned RefCount = CollCount (&L->JumpFrom);
for (K = 0; K < RefCount; ++K) {
/* 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);
}
/* Delete the label */
FreeCodeLabel (L);
/* Remove it from the list */
CollDelete (&E->Labels, J);
}
}
}

107
src/cc65/codeseg.h Normal file
View File

@ -0,0 +1,107 @@
/*****************************************************************************/
/* */
/* codeseg.h */
/* */
/* Code segment structure */
/* */
/* */
/* */
/* (C) 2001 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 CODESEG_H
#define CODESEG_H
#include <stdio.h>
/* common */
#include "attrib.h"
#include "coll.h"
/* b6502 */
#include "label.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Size of the label hash table */
#define CS_LABEL_HASH_SIZE 29
/* Code segment structure */
typedef struct CodeSeg CodeSeg;
struct CodeSeg {
char* Name; /* Segment name */
Collection Entries; /* List of code entries */
Collection Labels; /* Labels for next insn */
CodeLabel* LabelHash [CS_LABEL_HASH_SIZE]; /* Label hash table */
};
/*****************************************************************************/
/* Code */
/*****************************************************************************/
CodeSeg* NewCodeSeg (const char* Name);
/* Create a new code segment, initialize and return it */
void FreeCodeSeg (CodeSeg* S);
/* Free a code segment including all code entries */
void AddCodeSegLine (CodeSeg* S, const char* Format, ...) attribute ((format(printf,2,3)));
/* Add a line to the given code segment */
void AddCodeSegLabel (CodeSeg* S, const char* Name);
/* Add a label for the next instruction to follow */
void OutputCodeSeg (FILE* F, const CodeSeg* S);
/* Output the code segment data to a file */
CodeLabel* FindCodeLabel (CodeSeg* S, const char* Name, unsigned Hash);
/* Find the label with the given name. Return the label or NULL if not found */
void MergeCodeLabels (CodeSeg* S);
/* Merge code labels. That means: For each instruction, remove all labels but
* one and adjust the code entries accordingly.
*/
/* End of codeseg.h */
#endif

132
src/cc65/dataseg.c Normal file
View File

@ -0,0 +1,132 @@
/*****************************************************************************/
/* */
/* dataseg.c */
/* */
/* Data segment structure */
/* */
/* */
/* */
/* (C) 2001 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. */
/* */
/*****************************************************************************/
/* common */
#include "xmalloc.h"
#include "xsprintf.h"
/* cc65 */
#include "dataseg.h"
/*****************************************************************************/
/* Code */
/*****************************************************************************/
DataSeg* NewDataSeg (void)
/* Create a new data segment, initialize and return it */
{
/* Allocate memory */
DataSeg* S = xmalloc (sizeof (DataSeg));
/* Initialize the fields */
InitCollection (&S->Lines);
/* Return the new struct */
return S;
}
void FreeDataSeg (DataSeg* S)
/* Free a data segment including all line entries */
{
unsigned I, Count;
/* Free the lines */
Count = CollCount (&S->Lines);
for (I = 0; I < Count; ++I) {
xfree (CollAt (&S->Lines, I));
}
/* Free the collection */
DoneCollection (&S->Lines);
/* Free the struct */
xfree (S);
}
void AppendDataSeg (DataSeg* Target, const DataSeg* Source)
/* Append the data from Source to Target */
{
unsigned I;
/* Append all lines from Source to Target */
unsigned Count = CollCount (&Source->Lines);
for (I = 0; I < Count; ++I) {
CollAppend (&Target->Lines, xstrdup (CollConstAt (&Source->Lines, I)));
}
}
void AddDataSegLine (DataSeg* S, const char* Format, ...)
/* Add a line to the given data segment */
{
va_list ap;
char Buf [256];
/* Format the line */
va_start (ap, Format);
xvsprintf (Buf, sizeof (Buf), Format, ap);
va_end (ap);
/* Add a copy to the data segment */
CollAppend (&S->Lines, xstrdup (Buf));
}
void OutputDataSeg (FILE* F, const DataSeg* S)
/* Output the data segment data to a file */
{
unsigned I;
/* Get the number of entries in this segment */
unsigned Count = CollCount (&S->Lines);
/* Output all entries */
for (I = 0; I < Count; ++I) {
fprintf (F, "%s\n", (const char*) CollConstAt (&S->Lines, I));
}
}

89
src/cc65/dataseg.h Normal file
View File

@ -0,0 +1,89 @@
/*****************************************************************************/
/* */
/* dataseg.h */
/* */
/* Data segment structure */
/* */
/* */
/* */
/* (C) 2001 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 DATASEG_H
#define DATASEG_H
#include <stdio.h>
/* common */
#include "attrib.h"
#include "coll.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
typedef struct DataSeg DataSeg;
struct DataSeg {
Collection Lines; /* List of code lines */
};
/*****************************************************************************/
/* Code */
/*****************************************************************************/
DataSeg* NewDataSeg (void);
/* Create a new data segment, initialize and return it */
void FreeDataSeg (DataSeg* S);
/* Free a data segment including all line entries */
void AppendDataSeg (DataSeg* Target, const DataSeg* Source);
/* Append the data from Source to Target. */
void AddDataSegLine (DataSeg* S, const char* Format, ...) attribute ((format(printf,2,3)));
/* Add a line to the given data segment */
void OutputDataSeg (FILE* F, const DataSeg* S);
/* Output the data segment data to a file */
/* End of dataseg.h */
#endif

View File

@ -3,30 +3,37 @@
#
# Library dir
# ------------------------------------------------------------------------------
# The executable to build
EXE = cc65
# Library directories
COMMON = ../common
B6502 = b6502
# Default for the compiler lib search path as compiler define
CDEFS=-DCC65_INC=\"/usr/lib/cc65/include/\"
CFLAGS = -O2 -g -Wall -I$(COMMON) $(CDEFS)
CFLAGS = -O2 -g -Wall -I$(COMMON) -I$(B6502) $(CDEFS)
CC=gcc
EBIND=emxbind
LDFLAGS=
# ------------------------------------------------------------------------------
# Object files and libraries to link
OBJS = anonname.o \
asmcode.o \
asmcode.o \
asmlabel.o \
asmline.o \
codeent.o \
codegen.o \
codeseg.o \
compile.o \
cpu.o \
dataseg.o \
asmline.o \
codegen.o \
compile.o \
cpu.o \
datatype.o \
declare.o \
declattr.o \
error.o \
error.o \
expr.o \
exprheap.o \
exprnode.o \
@ -42,7 +49,6 @@ OBJS = anonname.o \
loop.o \
macrotab.o \
main.o \
opcodes.o \
optimize.o \
preproc.o \
pragma.o \
@ -55,30 +61,32 @@ OBJS = anonname.o \
typecmp.o \
util.o
LIBS = $(COMMON)/common.a
EXECS = cc65
LIBS = $(COMMON)/common.a \
$(B6502)/b6502.a
# ------------------------------------------------------------------------------
# Makefile targets
# Main target - must be first
.PHONY: all
ifeq (.depend,$(wildcard .depend))
all : $(EXECS)
all: $(EXE)
include .depend
else
all: depend
@$(MAKE) -f make/gcc.mak all
endif
cc65: $(OBJS)
$(CC) $(LDFLAGS) -o cc65 $(CFLAGS) $(OBJS) $(LIBS)
@if [ $(OS2_SHELL) ] ; then $(EBIND) cc65 ; fi
$(EXE): $(OBJS) $(LIBS)
$(CC) $(LDFLAGS) -o $(EXE) $(CFLAGS) $(OBJS) $(LIBS)
@if [ $(OS2_SHELL) ] ; then $(EBIND) $(EXE) ; fi
clean:
rm -f *~ core *.map
zap: clean
rm -f *.o $(EXECS) .depend
rm -f *.o $(EXE) .depend
# ------------------------------------------------------------------------------
# Make the dependencies
@ -86,6 +94,6 @@ zap: clean
.PHONY: depend dep
depend dep: $(OBJS:.o=.c)
@echo "Creating dependency information"
$(CC) -I$(COMMON) -MM $^ > .depend
$(CC) -I$(COMMON) -I$(B6502) -MM $^ > .depend

204
src/cc65/opcodes.c Normal file
View File

@ -0,0 +1,204 @@
/*****************************************************************************/
/* */
/* opcodes.c */
/* */
/* Opcode and addressing mode definitions */
/* */
/* */
/* */
/* (C) 2001 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 "stdlib.h"
#include <string.h>
#include <ctype.h>
/* common */
#include "check.h"
/* cc65 */
#include "codeinfo.h"
#include "opcodes.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Mapper table, mnemonic --> opcode */
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 },
{ "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 },
{ "clc", OPC_CLC, CI_CHG_NONE },
{ "cld", OPC_CLD, CI_CHG_NONE },
{ "cli", OPC_CLI, CI_CHG_NONE },
{ "clv", OPC_CLV, CI_CHG_NONE },
{ "cmp", OPC_CMP, CI_USE_A },
{ "cpx", OPC_CPX, CI_USE_X },
{ "cpy", OPC_CPY, CI_USE_Y },
{ "dea", OPC_DEA, CI_USE_A | CI_CHG_A },
{ "dec", OPC_DEC, CI_NONE },
{ "dex", OPC_DEX, CI_USE_X | CI_CHG_X },
{ "dey", OPC_DEY, CI_USE_Y | CI_CHG_Y },
{ "eor", OPC_EOR, CI_USE_A | CI_CHG_A },
{ "ina", OPC_INA, CI_USE_A | CI_CHG_A },
{ "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 },
{ "lda", OPC_LDA, CI_CHG_A },
{ "ldx", OPC_LDX, CI_CHG_X },
{ "ldy", OPC_LDY, CI_CHG_Y },
{ "lsr", OPC_LSR, CI_USE_A | CI_CHG_A },
{ "nop", OPC_NOP, CI_NONE },
{ "ora", OPC_ORA, CI_USE_A | CI_CHG_A },
{ "pha", OPC_PHA, CI_USE_A },
{ "php", OPC_PHP, CI_NONE },
{ "phx", OPC_PHX, CI_USE_X },
{ "phy", OPC_PHY, CI_USE_Y },
{ "pla", OPC_PLA, CI_CHG_A },
{ "plp", OPC_PLP, CI_NONE },
{ "plx", OPC_PLX, CI_CHG_X },
{ "ply", OPC_PLY, CI_CHG_Y },
{ "rol", OPC_ROL, CI_USE_A | CI_CHG_A },
{ "ror", OPC_ROR, CI_USE_A | CI_CHG_A },
{ "rti", OPC_RTI, CI_NONE },
{ "rts", OPC_RTS, CI_NONE },
{ "sbc", OPC_SBC, CI_USE_A | CI_CHG_A },
{ "sec", OPC_SEC, CI_NONE },
{ "sed", OPC_SED, CI_NONE },
{ "sei", OPC_SEI, CI_NONE },
{ "sta", OPC_STA, CI_USE_A },
{ "stx", OPC_STX, CI_USE_X },
{ "sty", OPC_STY, CI_USE_Y },
{ "tax", OPC_TAX, CI_USE_A | CI_CHG_X },
{ "tay", OPC_TAY, CI_USE_A | CI_CHG_Y },
{ "trb", OPC_TRB, CI_USE_A },
{ "tsb", OPC_TSB, CI_USE_A },
{ "tsx", OPC_TSX, CI_CHG_X },
{ "txa", OPC_TXA, CI_USE_X | CI_CHG_A },
{ "txs", OPC_TXS, CI_USE_X },
{ "tya", OPC_TYA, CI_USE_Y | CI_CHG_A }
};
/*****************************************************************************/
/* Code */
/*****************************************************************************/
static int Compare (const void* Key, const void* Desc)
/* Compare function for bsearch */
{
return strcmp (Key, ((OPCDesc*)Desc)->Mnemo);
}
const OPCDesc* FindOpcode (const char* M)
/* Find the given opcode and return the opcode number. If the opcode was not
* found, return OPC_INVALID.
*/
{
unsigned I;
unsigned Len;
/* Check the length of the given string, then copy it into local
* storage, converting it to upper case.
*/
char Mnemo[sizeof (OPCTable[0].Mnemo)];
Len = strlen (M);
if (Len >= sizeof (OPCTable[0].Mnemo)) {
/* Invalid length means invalid opcode */
return 0;
}
for (I = 0; I < Len; ++I) {
Mnemo[I] = tolower (M[I]);
}
Mnemo[I] = '\0';
/* Search for the mnemonic in the table and return the result */
return bsearch (Mnemo, OPCTable, OPC_COUNT, sizeof (OPCTable[0]), Compare);
}
unsigned GetInsnSize (opc_t OPC, am_t AM)
/* Return the size of the given instruction */
{
/* On the 6502 (and 65C02), the instruction size is determined only by the
* addressing mode.
*/
switch (AM) {
case AM_IMP: return 1;
case AM_IMM: return 2;
case AM_ZP: return 2;
case AM_ZPX: return 2;
case AM_ABS: return 3;
case AM_ABSX: return 3;
case AM_ABSY: return 3;
case AM_ZPX_IND: return 2;
case AM_ZP_INDY: return 2;
case AM_ZP_IND: return 2;
case AM_BRA: return 2;
default: FAIL ("Invalid addressing mode");
}
}
const OPCDesc* GetOPCDesc (opc_t OPC)
/* Get an opcode description */
{
/* Check the range */
PRECONDITION (OPC >= (opc_t)0 && OPC < OPC_COUNT);
/* Return the description */
return &OPCTable [OPC];
}

164
src/cc65/opcodes.h Normal file
View File

@ -0,0 +1,164 @@
/*****************************************************************************/
/* */
/* opcodes.h */
/* */
/* Opcode and addressing mode definitions */
/* */
/* */
/* */
/* (C) 2001 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 OPCODES_H
#define OPCODES_H
/*****************************************************************************/
/* Data */
/*****************************************************************************/
/* Definitions for the possible opcodes */
typedef enum {
OPC_ADC,
OPC_AND,
OPC_ASL,
OPC_BCC,
OPC_BCS,
OPC_BEQ,
OPC_BIT,
OPC_BMI,
OPC_BNE,
OPC_BPL,
OPC_BRA,
OPC_BRK,
OPC_BVC,
OPC_BVS,
OPC_CLC,
OPC_CLD,
OPC_CLI,
OPC_CLV,
OPC_CMP,
OPC_CPX,
OPC_CPY,
OPC_DEA,
OPC_DEC,
OPC_DEX,
OPC_DEY,
OPC_EOR,
OPC_INA,
OPC_INC,
OPC_INX,
OPC_INY,
OPC_JMP,
OPC_JSR,
OPC_LDA,
OPC_LDX,
OPC_LDY,
OPC_LSR,
OPC_NOP,
OPC_ORA,
OPC_PHA,
OPC_PHP,
OPC_PHX,
OPC_PHY,
OPC_PLA,
OPC_PLP,
OPC_PLX,
OPC_PLY,
OPC_ROL,
OPC_ROR,
OPC_RTI,
OPC_RTS,
OPC_SBC,
OPC_SEC,
OPC_SED,
OPC_SEI,
OPC_STA,
OPC_STX,
OPC_STY,
OPC_TAX,
OPC_TAY,
OPC_TRB,
OPC_TSB,
OPC_TSX,
OPC_TXA,
OPC_TXS,
OPC_TYA,
OPC_COUNT /* Number of opcodes available */
} opc_t;
/* 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_t;
/* Opcode description */
typedef struct {
char Mnemo[4]; /* Mnemonic */
opc_t OPC; /* Opcode */
unsigned Usage; /* Usage flags */
} OPCDesc;
/*****************************************************************************/
/* Code */
/*****************************************************************************/
const OPCDesc* FindOpcode (const char* OPC);
/* Find the given opcode and return the opcode description. If the opcode was
* not found, NULL is returned.
*/
unsigned GetInsnSize (opc_t OPC, am_t AM);
/* Return the size of the given instruction */
const OPCDesc* GetOPCDesc (opc_t OPC);
/* Get an opcode description */
/* End of opcodes.h */
#endif