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:
parent
ddc60c20fe
commit
aa6b3afcfc
170
src/cc65/codeent.c
Normal file
170
src/cc65/codeent.c
Normal 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
98
src/cc65/codeent.h
Normal 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
80
src/cc65/codeinfo.h
Normal 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
91
src/cc65/codelab.c
Normal 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
87
src/cc65/codelab.h
Normal 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
490
src/cc65/codeseg.c
Normal 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
107
src/cc65/codeseg.h
Normal 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
132
src/cc65/dataseg.c
Normal 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
89
src/cc65/dataseg.h
Normal 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
|
||||
|
||||
|
||||
|
@ -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
204
src/cc65/opcodes.c
Normal 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
164
src/cc65/opcodes.h
Normal 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
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user