From aa6b3afcfcca4f189ad45d4362af62514761b4d2 Mon Sep 17 00:00:00 2001 From: cuz Date: Mon, 30 Apr 2001 20:00:13 +0000 Subject: [PATCH] Working on the backend git-svn-id: svn://svn.cc65.org/cc65/trunk@699 b7a2c559-68d2-44c3-8de9-860c34a00d81 --- src/cc65/codeent.c | 170 +++++++++++++++ src/cc65/codeent.h | 98 +++++++++ src/cc65/codeinfo.h | 80 +++++++ src/cc65/codelab.c | 91 ++++++++ src/cc65/codelab.h | 87 ++++++++ src/cc65/codeseg.c | 490 ++++++++++++++++++++++++++++++++++++++++++ src/cc65/codeseg.h | 107 +++++++++ src/cc65/dataseg.c | 132 ++++++++++++ src/cc65/dataseg.h | 89 ++++++++ src/cc65/make/gcc.mak | 50 +++-- src/cc65/opcodes.c | 204 ++++++++++++++++++ src/cc65/opcodes.h | 164 ++++++++++++++ 12 files changed, 1741 insertions(+), 21 deletions(-) create mode 100644 src/cc65/codeent.c create mode 100644 src/cc65/codeent.h create mode 100644 src/cc65/codeinfo.h create mode 100644 src/cc65/codelab.c create mode 100644 src/cc65/codelab.h create mode 100644 src/cc65/codeseg.c create mode 100644 src/cc65/codeseg.h create mode 100644 src/cc65/dataseg.c create mode 100644 src/cc65/dataseg.h create mode 100644 src/cc65/opcodes.c create mode 100644 src/cc65/opcodes.h diff --git a/src/cc65/codeent.c b/src/cc65/codeent.c new file mode 100644 index 000000000..711ecf116 --- /dev/null +++ b/src/cc65/codeent.c @@ -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"); +} + + + + diff --git a/src/cc65/codeent.h b/src/cc65/codeent.h new file mode 100644 index 000000000..f627c9017 --- /dev/null +++ b/src/cc65/codeent.h @@ -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 + +/* 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 + + + diff --git a/src/cc65/codeinfo.h b/src/cc65/codeinfo.h new file mode 100644 index 000000000..49ba67046 --- /dev/null +++ b/src/cc65/codeinfo.h @@ -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 + + + diff --git a/src/cc65/codelab.c b/src/cc65/codelab.c new file mode 100644 index 000000000..823f2eb70 --- /dev/null +++ b/src/cc65/codelab.c @@ -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); +} + + + diff --git a/src/cc65/codelab.h b/src/cc65/codelab.h new file mode 100644 index 000000000..8fb3143e2 --- /dev/null +++ b/src/cc65/codelab.h @@ -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 + +/* 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 + + + diff --git a/src/cc65/codeseg.c b/src/cc65/codeseg.c new file mode 100644 index 000000000..98f4cdd6f --- /dev/null +++ b/src/cc65/codeseg.c @@ -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 +#include + +/* 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); + + } + } +} + + + diff --git a/src/cc65/codeseg.h b/src/cc65/codeseg.h new file mode 100644 index 000000000..535cd53fc --- /dev/null +++ b/src/cc65/codeseg.h @@ -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 + +/* 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 + + + diff --git a/src/cc65/dataseg.c b/src/cc65/dataseg.c new file mode 100644 index 000000000..8940c6b8a --- /dev/null +++ b/src/cc65/dataseg.c @@ -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)); + } +} + + + diff --git a/src/cc65/dataseg.h b/src/cc65/dataseg.h new file mode 100644 index 000000000..328962f82 --- /dev/null +++ b/src/cc65/dataseg.h @@ -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 + +/* 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 + + + diff --git a/src/cc65/make/gcc.mak b/src/cc65/make/gcc.mak index 0ddff5a93..ea67295a3 100644 --- a/src/cc65/make/gcc.mak +++ b/src/cc65/make/gcc.mak @@ -3,30 +3,37 @@ # -# Library dir + +# ------------------------------------------------------------------------------ + +# The executable to build +EXE = cc65 + +# Library directories COMMON = ../common +B6502 = b6502 # Default for the compiler lib search path as compiler define CDEFS=-DCC65_INC=\"/usr/lib/cc65/include/\" -CFLAGS = -O2 -g -Wall -I$(COMMON) $(CDEFS) +CFLAGS = -O2 -g -Wall -I$(COMMON) -I$(B6502) $(CDEFS) CC=gcc EBIND=emxbind LDFLAGS= +# ------------------------------------------------------------------------------ +# Object files and libraries to link + OBJS = anonname.o \ - asmcode.o \ + asmcode.o \ asmlabel.o \ - asmline.o \ - codeent.o \ - codegen.o \ - codeseg.o \ - compile.o \ - cpu.o \ - dataseg.o \ + asmline.o \ + codegen.o \ + compile.o \ + cpu.o \ datatype.o \ declare.o \ declattr.o \ - error.o \ + error.o \ expr.o \ exprheap.o \ exprnode.o \ @@ -42,7 +49,6 @@ OBJS = anonname.o \ loop.o \ macrotab.o \ main.o \ - opcodes.o \ optimize.o \ preproc.o \ pragma.o \ @@ -55,30 +61,32 @@ OBJS = anonname.o \ typecmp.o \ util.o -LIBS = $(COMMON)/common.a +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 @@ -86,6 +94,6 @@ zap: clean .PHONY: depend dep depend dep: $(OBJS:.o=.c) @echo "Creating dependency information" - $(CC) -I$(COMMON) -MM $^ > .depend + $(CC) -I$(COMMON) -I$(B6502) -MM $^ > .depend diff --git a/src/cc65/opcodes.c b/src/cc65/opcodes.c new file mode 100644 index 000000000..84ab69307 --- /dev/null +++ b/src/cc65/opcodes.c @@ -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 +#include + +/* 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]; +} + + + + diff --git a/src/cc65/opcodes.h b/src/cc65/opcodes.h new file mode 100644 index 000000000..7bcda632d --- /dev/null +++ b/src/cc65/opcodes.h @@ -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 + + + -- 2.39.2