Working on the backend
git-svn-id: svn://svn.cc65.org/cc65/trunk@699 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
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
|
COMMON = ../common
|
||||||
|
B6502 = b6502
|
||||||
|
|
||||||
# Default for the compiler lib search path as compiler define
|
# Default for the compiler lib search path as compiler define
|
||||||
CDEFS=-DCC65_INC=\"/usr/lib/cc65/include/\"
|
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
|
CC=gcc
|
||||||
EBIND=emxbind
|
EBIND=emxbind
|
||||||
LDFLAGS=
|
LDFLAGS=
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Object files and libraries to link
|
||||||
|
|
||||||
OBJS = anonname.o \
|
OBJS = anonname.o \
|
||||||
asmcode.o \
|
asmcode.o \
|
||||||
asmlabel.o \
|
asmlabel.o \
|
||||||
asmline.o \
|
asmline.o \
|
||||||
codeent.o \
|
codegen.o \
|
||||||
codegen.o \
|
compile.o \
|
||||||
codeseg.o \
|
cpu.o \
|
||||||
compile.o \
|
|
||||||
cpu.o \
|
|
||||||
dataseg.o \
|
|
||||||
datatype.o \
|
datatype.o \
|
||||||
declare.o \
|
declare.o \
|
||||||
declattr.o \
|
declattr.o \
|
||||||
error.o \
|
error.o \
|
||||||
expr.o \
|
expr.o \
|
||||||
exprheap.o \
|
exprheap.o \
|
||||||
exprnode.o \
|
exprnode.o \
|
||||||
@@ -42,7 +49,6 @@ OBJS = anonname.o \
|
|||||||
loop.o \
|
loop.o \
|
||||||
macrotab.o \
|
macrotab.o \
|
||||||
main.o \
|
main.o \
|
||||||
opcodes.o \
|
|
||||||
optimize.o \
|
optimize.o \
|
||||||
preproc.o \
|
preproc.o \
|
||||||
pragma.o \
|
pragma.o \
|
||||||
@@ -55,30 +61,32 @@ OBJS = anonname.o \
|
|||||||
typecmp.o \
|
typecmp.o \
|
||||||
util.o
|
util.o
|
||||||
|
|
||||||
LIBS = $(COMMON)/common.a
|
LIBS = $(COMMON)/common.a \
|
||||||
|
$(B6502)/b6502.a
|
||||||
EXECS = cc65
|
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# Makefile targets
|
||||||
|
|
||||||
|
# Main target - must be first
|
||||||
.PHONY: all
|
.PHONY: all
|
||||||
ifeq (.depend,$(wildcard .depend))
|
ifeq (.depend,$(wildcard .depend))
|
||||||
all : $(EXECS)
|
all: $(EXE)
|
||||||
include .depend
|
include .depend
|
||||||
else
|
else
|
||||||
all: depend
|
all: depend
|
||||||
@$(MAKE) -f make/gcc.mak all
|
@$(MAKE) -f make/gcc.mak all
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
$(EXE): $(OBJS) $(LIBS)
|
||||||
cc65: $(OBJS)
|
$(CC) $(LDFLAGS) -o $(EXE) $(CFLAGS) $(OBJS) $(LIBS)
|
||||||
$(CC) $(LDFLAGS) -o cc65 $(CFLAGS) $(OBJS) $(LIBS)
|
@if [ $(OS2_SHELL) ] ; then $(EBIND) $(EXE) ; fi
|
||||||
@if [ $(OS2_SHELL) ] ; then $(EBIND) cc65 ; fi
|
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f *~ core *.map
|
rm -f *~ core *.map
|
||||||
|
|
||||||
zap: clean
|
zap: clean
|
||||||
rm -f *.o $(EXECS) .depend
|
rm -f *.o $(EXE) .depend
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Make the dependencies
|
# Make the dependencies
|
||||||
@@ -86,6 +94,6 @@ zap: clean
|
|||||||
.PHONY: depend dep
|
.PHONY: depend dep
|
||||||
depend dep: $(OBJS:.o=.c)
|
depend dep: $(OBJS:.o=.c)
|
||||||
@echo "Creating dependency information"
|
@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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user