--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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");
+}
+
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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);
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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);
+
+ }
+ }
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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));
+ }
+}
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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
+
+
+
#
-# 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 \
loop.o \
macrotab.o \
main.o \
- opcodes.o \
optimize.o \
preproc.o \
pragma.o \
typecmp.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
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
.PHONY: depend dep
depend dep: $(OBJS:.o=.c)
@echo "Creating dependency information"
- $(CC) -I$(COMMON) -MM $^ > .depend
+ $(CC) -I$(COMMON) -I$(B6502) -MM $^ > .depend
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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];
+}
+
+
+
+
--- /dev/null
+/*****************************************************************************/
+/* */
+/* 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
+
+
+