1
0
mirror of https://github.com/cc65/cc65.git synced 2024-06-02 04:41:35 +00:00

Working on the backend

git-svn-id: svn://svn.cc65.org/cc65/trunk@729 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2001-05-16 19:01:19 +00:00
parent 1d3ea5cde0
commit 09eed789dd
9 changed files with 594 additions and 185 deletions

View File

@ -139,10 +139,13 @@ static int NumArg (const char* Arg, unsigned long* Num)
CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, const char* Arg, CodeLabel* JumpTo)
CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg, CodeLabel* JumpTo)
/* Create a new code entry, initialize and return it */
{
/* Allocate memory */
/* Get the opcode description */
const OPCDesc* D = GetOPCDesc (OPC);
/* Allocate memory */
CodeEntry* E = xmalloc (sizeof (CodeEntry));
/* Initialize the fields */
@ -246,30 +249,6 @@ void AttachCodeLabel (CodeEntry* E, CodeLabel* L)
int CodeEntryHasLabel (const CodeEntry* E)
/* Check if the given code entry has labels attached */
{
return (CollCount (&E->Labels) > 0);
}
unsigned GetCodeLabelCount (const CodeEntry* E)
/* Get the number of labels attached to this entry */
{
return CollCount (&E->Labels);
}
CodeLabel* GetCodeLabel (CodeEntry* E, unsigned Index)
/* Get a label from this code entry */
{
return CollAt (&E->Labels, Index);
}
void MoveCodeLabel (CodeLabel* L, CodeEntry* E)
/* Move the code label L from it's former owner to the code entry E. */
{
@ -283,30 +262,6 @@ void MoveCodeLabel (CodeLabel* L, CodeEntry* E)
int CodeEntryHasMark (const CodeEntry* E)
/* Return true if the given code entry has the CEF_USERMARK flag set */
{
return (E->Flags & CEF_USERMARK) != 0;
}
void CodeEntrySetMark (CodeEntry* E)
/* Set the CEF_USERMARK flag for the given entry */
{
E->Flags |= CEF_USERMARK;
}
void CodeEntryResetMark (CodeEntry* E)
/* Reset the CEF_USERMARK flag for the given entry */
{
E->Flags &= ~CEF_USERMARK;
}
void CodeEntrySetArg (CodeEntry* E, const char* Arg)
/* Set a new argument for the given code entry. An old string is deleted. */
{

View File

@ -42,6 +42,7 @@
/* common */
#include "coll.h"
#include "inline.h"
/* cc65 */
#include "codelab.h"
@ -84,7 +85,7 @@ struct CodeEntry {
CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, const char* Arg, CodeLabel* JumpTo);
CodeEntry* NewCodeEntry (opc_t OPC, am_t AM, const char* Arg, CodeLabel* JumpTo);
/* Create a new code entry, initialize and return it */
void FreeCodeEntry (CodeEntry* E);
@ -101,26 +102,68 @@ int CodeEntriesAreEqual (const CodeEntry* E1, const CodeEntry* E2);
void AttachCodeLabel (CodeEntry* E, CodeLabel* L);
/* Attach the label to the entry */
int CodeEntryHasLabel (const CodeEntry* E);
#if defined(HAVE_INLINE)
INLINE int CodeEntryHasLabel (const CodeEntry* E)
/* Check if the given code entry has labels attached */
{
return (CollCount (&E->Labels) > 0);
}
#else
# define CodeEntryHasLabel(E) (CollCount (&(E)->Labels) > 0)
#endif
unsigned GetCodeLabelCount (const CodeEntry* E);
#if defined(HAVE_INLINE)
INLINE unsigned GetCodeLabelCount (const CodeEntry* E)
/* Get the number of labels attached to this entry */
{
return CollCount (&E->Labels);
}
#else
# define GetCodeLabelCount(E) CollCount (&(E)->Labels)
#endif
CodeLabel* GetCodeLabel (CodeEntry* E, unsigned Index);
#if defined(HAVE_INLINE)
INLINE CodeLabel* GetCodeLabel (CodeEntry* E, unsigned Index)
/* Get a label from this code entry */
{
return CollAt (&E->Labels, Index);
}
#else
# define GetCodeLabel(E, Index) CollAt (&(E)->Labels, (Index))
#endif
void MoveCodeLabel (CodeLabel* L, CodeEntry* E);
/* Move the code label L from it's former owner to the code entry E. */
int CodeEntryHasMark (const CodeEntry* E);
#if defined(HAVE_INLINE)
INLINE int CodeEntryHasMark (const CodeEntry* E)
/* Return true if the given code entry has the CEF_USERMARK flag set */
{
return (E->Flags & CEF_USERMARK) != 0;
}
#else
# define CodeEntryHasMark(E) (((E)->Flags & CEF_USERMARK) != 0)
#endif
void CodeEntrySetMark (CodeEntry* E);
#if defined(HAVE_INLINE)
INLINE void CodeEntrySetMark (CodeEntry* E)
/* Set the CEF_USERMARK flag for the given entry */
{
E->Flags |= CEF_USERMARK;
}
#else
# define CodeEntrySetMark(E) ((E)->Flags |= CEF_USERMARK)
#endif
void CodeEntryResetMark (CodeEntry* E);
#if defined(HAVE_INLINE)
INLINE void CodeEntryResetMark (CodeEntry* E)
/* Reset the CEF_USERMARK flag for the given entry */
{
E->Flags &= ~CEF_USERMARK;
}
#else
# define CodeEntryResetMark(E) ((E)->Flags &= ~CEF_USERMARK)
#endif
void CodeEntrySetArg (CodeEntry* E, const char* Arg);
/* Set a new argument for the given code entry. An old string is deleted. */

View File

@ -242,6 +242,322 @@ NextEntry:
/*****************************************************************************/
/* nega optimizations */
/*****************************************************************************/
static unsigned OptNegA1 (CodeSeg* S)
/* Check for
*
* ldx #$00
* lda ..
* jsr bnega
*
* Remove the ldx if the lda does not use it.
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < GetCodeEntryCount (S)) {
CodeEntry* L[2];
/* Get next entry */
CodeEntry* E = GetCodeEntry (S, I);
/* Check for a ldx */
if (E->OPC == OPC_LDX &&
E->AM == AM_IMM &&
(E->Flags & CEF_NUMARG) != 0 &&
E->Num == 0 &&
GetCodeEntries (S, L, I+1, 2) &&
L[0]->OPC == OPC_LDA &&
(L[0]->Use & REG_X) == 0 &&
L[1]->OPC == OPC_JSR &&
strcmp (L[1]->Arg, "bnega") == 0) {
/* Remove the ldx instruction */
DelCodeEntry (S, I);
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
static unsigned OptNegA2 (CodeSeg* S)
/* Check for
*
* lda ..
* jsr bnega
* jeq/jne ..
*
* Adjust the conditional branch and remove the call to the subroutine.
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < GetCodeEntryCount (S)) {
CodeEntry* L[2];
/* Get next entry */
CodeEntry* E = GetCodeEntry (S, I);
/* Check for the sequence */
if (E->OPC == OPC_LDA &&
GetCodeEntries (S, L, I+1, 2) &&
L[0]->OPC == OPC_JSR &&
strcmp (L[0]->Arg, "bnega") == 0 &&
!CodeEntryHasLabel (L[0]) &&
(L[1]->Info & OF_ZBRA) != 0) {
/* Invert the branch */
ReplaceOPC (L[1], GetInverseBranch (L[1]->OPC));
/* Delete the subroutine call */
DelCodeEntry (S, I+1);
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
/*****************************************************************************/
/* negax optimizations */
/*****************************************************************************/
static unsigned OptNegAX1 (CodeSeg* S)
/* Search for the sequence:
*
* lda (xx),y
* tax
* dey
* lda (xx),y
* jsr bnegax
* jne/jeq ...
*
* and replace it by
*
* lda (xx),y
* dey
* ora (xx),y
* jeq/jne ...
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < GetCodeEntryCount (S)) {
CodeEntry* L[5];
/* Get next entry */
CodeEntry* E = GetCodeEntry (S, I);
/* Check for the sequence */
if (E->OPC == OPC_LDA &&
E->AM == AM_ZP_INDY &&
GetCodeEntries (S, L, I+1, 5) &&
L[0]->OPC == OPC_TAX &&
L[1]->OPC == OPC_DEY &&
L[2]->OPC == OPC_LDA &&
L[2]->AM == AM_ZP_INDY &&
strcmp (L[2]->Arg, E->Arg) == 0 &&
!CodeEntryHasLabel (L[2]) &&
L[3]->OPC == OPC_JSR &&
strcmp (L[3]->Arg, "bnegax") == 0 &&
!CodeEntryHasLabel (L[3]) &&
(L[4]->Info & OF_ZBRA) != 0) {
/* lda --> ora */
ReplaceOPC (L[2], OPC_ORA);
/* Invert the branch */
ReplaceOPC (L[4], GetInverseBranch (L[4]->OPC));
/* Delete the entries no longer needed. Beware: Deleting entries
* will change the indices.
*/
DelCodeEntry (S, I+4); /* jsr bnegax */
DelCodeEntry (S, I+1); /* tax */
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
static unsigned OptNegAX2 (CodeSeg* S)
/* Search for the sequence:
*
* lda xx
* ldx yy
* jsr bnegax
* jne/jeq ...
*
* and replace it by
*
* lda xx
* ora xx+1
* jeq/jne ...
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < GetCodeEntryCount (S)) {
CodeEntry* L[3];
/* Get next entry */
CodeEntry* E = GetCodeEntry (S, I);
/* Check for the sequence */
if (E->OPC == OPC_LDA &&
GetCodeEntries (S, L, I+1, 3) &&
L[0]->OPC == OPC_LDX &&
!CodeEntryHasLabel (L[0]) &&
L[1]->OPC == OPC_JSR &&
strcmp (L[1]->Arg, "bnegax") == 0 &&
!CodeEntryHasLabel (L[1]) &&
(L[2]->Info & OF_ZBRA) != 0) {
/* ldx --> ora */
ReplaceOPC (L[0], OPC_ORA);
/* Invert the branch */
ReplaceOPC (L[2], GetInverseBranch (L[2]->OPC));
/* Delete the subroutine call */
DelCodeEntry (S, I+2);
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
static unsigned OptNegAX3 (CodeSeg* S)
/* Search for the sequence:
*
* jsr _xxx
* jsr bnega(x)
* jeq/jne ...
*
* and replace it by:
*
* jsr _xxx
* <boolean test>
* jne/jeq ...
*/
{
unsigned Changes = 0;
/* Walk over the entries */
unsigned I = 0;
while (I < GetCodeEntryCount (S)) {
CodeEntry* L[2];
/* Get next entry */
CodeEntry* E = GetCodeEntry (S, I);
/* Check for the sequence */
if (E->OPC == OPC_JSR &&
E->Arg[0] == '_' &&
GetCodeEntries (S, L, I+1, 2) &&
L[0]->OPC == OPC_JSR &&
strncmp (L[0]->Arg,"bnega",5) == 0 &&
!CodeEntryHasLabel (L[0]) &&
(L[1]->Info & OF_ZBRA) != 0) {
/* Check if we're calling bnega or bnegax */
int ByteSized = (strcmp (L[0]->Arg, "bnega") == 0);
/* Delete the subroutine call */
DelCodeEntry (S, I+1);
/* Insert apropriate test code */
if (ByteSized) {
/* Test bytes */
InsertCodeEntry (S, NewCodeEntry (OPC_TAX, AM_IMP, 0, 0), I+1);
} else {
/* Test words */
InsertCodeEntry (S, NewCodeEntry (OPC_STX, AM_ZP, "tmp1", 0), I+1);
InsertCodeEntry (S, NewCodeEntry (OPC_ORA, AM_ZP, "tmp1", 0), I+2);
}
/* Invert the branch */
ReplaceOPC (L[1], GetInverseBranch (L[1]->OPC));
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
/*****************************************************************************/
/* Code */
/*****************************************************************************/
@ -271,9 +587,21 @@ static OptFunc OptFuncs [] = {
/* Optimize jump targets */
{ OptJumpTarget, "OptJumpTarget", 0 },
/* Optimize conditional branches */
{ OptCondBranches, "OptCondBranches", 0 },
{ OptCondBranches, "OptCondBranches", 0 },
/* Replace jumps to RTS by RTS */
{ OptRTSJumps, "OptRTSJumps", 0 },
/* Remove calls to the bool transformer subroutines */
{ OptBoolTransforms, "OptBoolTransforms", 0 },
/* Optimize calls to nega */
{ OptNegA1, "OptNegA1", 0 },
/* Optimize calls to nega */
{ OptNegA2, "OptNegA2", 0 },
/* Optimize calls to negax */
{ OptNegAX1, "OptNegAX1", 0 },
/* Optimize calls to negax */
{ OptNegAX2, "OptNegAX2", 0 },
/* Optimize calls to negax */
{ OptNegAX3, "OptNegAX3", 0 },
/* Remove unused loads */
{ OptUnusedLoads, "OptUnusedLoads", 0 },
/* Optimize branch distance */

View File

@ -155,7 +155,7 @@ static const char* SkipSpace (const char* S)
static const char* ReadToken (const char* L, const char* Term,
char* Buf, unsigned BufSize)
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.
*/
@ -181,7 +181,7 @@ static const char* ReadToken (const char* L, const char* Term,
/* Return the updated line pointer */
return L;
}
static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
@ -197,7 +197,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
am_t AM = 0; /* Initialize to keep gcc silent */
char Arg[64];
char Reg;
CodeEntry* E;
CodeEntry* E;
CodeLabel* Label;
/* Mnemonic */
@ -353,7 +353,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
/* We do now have the addressing mode in AM. Allocate a new CodeEntry
* structure and initialize it.
*/
E = NewCodeEntry (OPC, AM, Arg, Label);
E = NewCodeEntry (OPC->OPC, AM, Arg, Label);
/* Return the new code entry */
return E;
@ -393,7 +393,7 @@ CodeSeg* NewCodeSeg (const char* SegName, SymEntry* Func)
S->ExitRegs = REG_NONE;
}
/* Return the new struct */
/* Return the new struct */
return S;
}
@ -527,14 +527,6 @@ void DelCodeEntry (CodeSeg* S, unsigned Index)
struct CodeEntry* GetCodeEntry (CodeSeg* S, unsigned Index)
/* Get an entry from the given code segment */
{
return CollAt (&S->Entries, Index);
}
struct CodeEntry* GetNextCodeEntry (CodeSeg* S, unsigned Index)
/* Get the code entry following the one with the index Index. If there is no
* following code entry, return NULL.
@ -545,12 +537,34 @@ struct CodeEntry* GetNextCodeEntry (CodeSeg* S, unsigned Index)
return 0;
} else {
/* Code entries left */
return CollAt (&S->Entries, Index+1);
return CollAtUnchecked (&S->Entries, Index+1);
}
}
int GetCodeEntries (CodeSeg* S, struct CodeEntry** List,
unsigned Start, unsigned Count)
/* Get Count code entries into List starting at index start. Return true if
* we got the lines, return false if not enough lines were available.
*/
{
/* Check if enough entries are available */
if (Start + Count > CollCount (&S->Entries)) {
return 0;
}
/* Copy the entries */
while (Count--) {
*List++ = CollAtUnchecked (&S->Entries, Start++);
}
/* We have the entries */
return 1;
}
unsigned GetCodeEntryIndex (CodeSeg* S, struct CodeEntry* E)
/* Return the index of a code entry */
{
@ -917,11 +931,6 @@ void OutputCodeSeg (const CodeSeg* S, FILE* F)
unsigned GetCodeEntryCount (const CodeSeg* S)
/* Return the number of entries for the given code segment */
{
return CollCount (&S->Entries);
}

View File

@ -44,6 +44,7 @@
/* common */
#include "attrib.h"
#include "coll.h"
#include "inline.h"
/* cc65 */
#include "codelab.h"
@ -106,14 +107,27 @@ void DelCodeEntry (CodeSeg* S, unsigned Index);
* if the reference count drops to zero.
*/
struct CodeEntry* GetCodeEntry (CodeSeg* S, unsigned Index);
#if defined(HAVE_INLINE)
INLINE struct CodeEntry* GetCodeEntry (CodeSeg* S, unsigned Index)
/* Get an entry from the given code segment */
{
return CollAt (&S->Entries, Index);
}
#else
# define GetCodeEntry(S, Index) CollAt(&(S)->Entries, (Index))
#endif
struct CodeEntry* GetNextCodeEntry (CodeSeg* S, unsigned Index);
/* Get the code entry following the one with the index Index. If there is no
* following code entry, return NULL.
*/
int GetCodeEntries (CodeSeg* S, struct CodeEntry** List,
unsigned Start, unsigned Count);
/* Get Count code entries into List starting at index start. Return true if
* we got the lines, return false if not enough lines were available.
*/
unsigned GetCodeEntryIndex (CodeSeg* S, struct CodeEntry* E);
/* Return the index of a code entry */
@ -162,8 +176,15 @@ void DelCodeSegAfter (CodeSeg* S, unsigned Last);
void OutputCodeSeg (const CodeSeg* S, FILE* F);
/* Output the code segment data to a file */
unsigned GetCodeEntryCount (const CodeSeg* S);
#if defined(HAVE_INLINE)
INLINE unsigned GetCodeEntryCount (const CodeSeg* S)
/* Return the number of entries for the given code segment */
{
return CollCount (&S->Entries);
}
#else
# define GetCodeEntryCount(S) CollCount (&(S)->Entries)
#endif

View File

@ -44,6 +44,51 @@
/*****************************************************************************/
/* Replace jumps to RTS by RTS */
/*****************************************************************************/
unsigned OptRTSJumps (CodeSeg* S)
/* Replace jumps to RTS by RTS */
{
unsigned Changes = 0;
/* Walk over all entries minus the last one */
unsigned I = 0;
while (I < GetCodeEntryCount (S)) {
/* Get the next entry */
CodeEntry* E = GetCodeEntry (S, I);
/* Check if it's an unconditional branch to a local target */
if ((E->Info & OF_UBRA) != 0 &&
E->JumpTo != 0 &&
E->JumpTo->Owner->OPC == OPC_RTS) {
/* Delete the jump */
DelCodeEntry (S, I);
/* Insert an RTS instruction instead */
InsertCodeEntry (S, NewCodeEntry (OPC_RTS, AM_IMP, 0, 0), I);
/* Remember, we had changes */
++Changes;
}
/* Next entry */
++I;
}
/* Return the number of changes made */
return Changes;
}
/*****************************************************************************/
/* Remove dead jumps */
/*****************************************************************************/
@ -118,9 +163,11 @@ unsigned OptDeadCode (CodeSeg* S)
return 0;
}
/* Walk over all entries minus the last one */
/* Walk over all entries */
I = 0;
while (I < Count-1) {
while (I < Count) {
CodeEntry* N;
/* Get this entry */
CodeEntry* E = GetCodeEntry (S, I);
@ -128,7 +175,9 @@ unsigned OptDeadCode (CodeSeg* S)
/* Check if it's an unconditional branch, and if the next entry has
* no labels attached
*/
if ((E->Info & OF_DEAD) != 0 && !CodeEntryHasLabel (GetCodeEntry (S, I+1))) {
if ((E->Info & OF_DEAD) != 0 &&
(N = GetNextCodeEntry (S, I)) != 0 &&
!CodeEntryHasLabel (N)) {
/* Delete the next entry */
DelCodeEntry (S, I+1);

View File

@ -48,7 +48,10 @@
unsigned OptDeadJumps (CodeSeg* S);
unsigned OptRTSJumps (CodeSeg* S);
/* Replace jumps to RTS by RTS */
unsigned OptDeadJumps (CodeSeg* S);
/* Remove dead jumps (jumps to the next instruction) */
unsigned OptDeadCode (CodeSeg* S);

View File

@ -54,81 +54,81 @@
/* Mapper table, mnemonic --> opcode */
static const OPCDesc OPCTable[OPC_COUNT] = {
{ OPC_ADC, "adc", 0, REG_A, REG_A, OF_NONE },
{ OPC_AND, "and", 0, REG_A, REG_A, OF_NONE },
{ OPC_ASL, "asl", 0, REG_A, REG_A, OF_NONE },
{ OPC_BCC, "bcc", 2, REG_NONE, REG_NONE, OF_CBRA },
{ OPC_BCS, "bcs", 2, REG_NONE, REG_NONE, OF_CBRA },
{ OPC_BEQ, "beq", 2, REG_NONE, REG_NONE, OF_CBRA },
{ OPC_BIT, "bit", 0, REG_A, REG_NONE, OF_NONE },
{ OPC_BMI, "bmi", 2, REG_NONE, REG_NONE, OF_CBRA },
{ OPC_BNE, "bne", 2, REG_NONE, REG_NONE, OF_CBRA },
{ OPC_BPL, "bpl", 2, REG_NONE, REG_NONE, OF_CBRA },
{ OPC_BRA, "bra", 2, REG_NONE, REG_NONE, OF_UBRA },
{ OPC_BRK, "brk", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_BVC, "bvc", 2, REG_NONE, REG_NONE, OF_CBRA },
{ OPC_BVS, "bvs", 2, REG_NONE, REG_NONE, OF_CBRA },
{ OPC_CLC, "clc", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_CLD, "cld", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_CLI, "cli", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_CLV, "clv", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_CMP, "cmp", 0, REG_A, REG_NONE, OF_NONE },
{ OPC_CPX, "cpx", 0, REG_X, REG_NONE, OF_NONE },
{ OPC_CPY, "cpy", 0, REG_Y, REG_NONE, OF_NONE },
{ OPC_DEA, "dea", 1, REG_A, REG_A, OF_NONE },
{ OPC_DEC, "dec", 0, REG_NONE, REG_NONE, OF_NONE },
{ OPC_DEX, "dex", 1, REG_X, REG_X, OF_NONE },
{ OPC_DEY, "dey", 1, REG_Y, REG_Y, OF_NONE },
{ OPC_EOR, "eor", 0, REG_A, REG_A, OF_NONE },
{ OPC_INA, "ina", 1, REG_A, REG_A, OF_NONE },
{ OPC_INC, "inc", 0, REG_NONE, REG_NONE, OF_NONE },
{ OPC_INX, "inx", 1, REG_X, REG_X, OF_NONE },
{ OPC_INY, "iny", 1, REG_Y, REG_Y, OF_NONE },
{ OPC_JCC, "jcc", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
{ OPC_JCS, "jcs", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
{ OPC_JEQ, "jeq", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
{ OPC_JMI, "jmi", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
{ OPC_JMP, "jmp", 3, REG_NONE, REG_NONE, OF_UBRA | OF_LBRA },
{ OPC_JNE, "jne", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
{ OPC_JPL, "jpl", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
{ OPC_JSR, "jsr", 3, REG_NONE, REG_NONE, OF_NONE },
{ OPC_JVC, "jvc", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
{ OPC_JVS, "jvs", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
{ OPC_LDA, "lda", 0, REG_NONE, REG_A, OF_LOAD },
{ OPC_LDX, "ldx", 0, REG_NONE, REG_X, OF_LOAD },
{ OPC_LDY, "ldy", 0, REG_NONE, REG_Y, OF_LOAD },
{ OPC_LSR, "lsr", 0, REG_A, REG_A, OF_NONE },
{ OPC_NOP, "nop", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_ORA, "ora", 0, REG_A, REG_A, OF_NONE },
{ OPC_PHA, "pha", 1, REG_A, REG_NONE, OF_NONE },
{ OPC_PHP, "php", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_PHX, "phx", 1, REG_X, REG_NONE, OF_NONE },
{ OPC_PHY, "phy", 1, REG_Y, REG_NONE, OF_NONE },
{ OPC_PLA, "pla", 1, REG_NONE, REG_A, OF_NONE },
{ OPC_PLP, "plp", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_PLX, "plx", 1, REG_NONE, REG_X, OF_NONE },
{ OPC_PLY, "ply", 1, REG_NONE, REG_Y, OF_NONE },
{ OPC_ROL, "rol", 0, REG_A, REG_A, OF_NONE },
{ OPC_ROR, "ror", 0, REG_A, REG_A, OF_NONE },
{ OPC_RTI, "rti", 1, REG_NONE, REG_NONE, OF_RET },
{ OPC_RTS, "rts", 1, REG_NONE, REG_NONE, OF_RET },
{ OPC_SBC, "sbc", 0, REG_A, REG_A, OF_NONE },
{ OPC_SEC, "sec", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_SED, "sed", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_SEI, "sei", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_STA, "sta", 0, REG_A, REG_NONE, OF_NONE },
{ OPC_STX, "stx", 0, REG_X, REG_NONE, OF_NONE },
{ OPC_STY, "sty", 0, REG_Y, REG_NONE, OF_NONE },
{ OPC_TAX, "tax", 1, REG_A, REG_X, OF_NONE },
{ OPC_TAY, "tay", 1, REG_A, REG_Y, OF_NONE },
{ OPC_TRB, "trb", 0, REG_A, REG_NONE, OF_NONE },
{ OPC_TSB, "tsb", 0, REG_A, REG_NONE, OF_NONE },
{ OPC_TSX, "tsx", 1, REG_NONE, REG_X, OF_NONE },
{ OPC_TXA, "txa", 1, REG_X, REG_A, OF_NONE },
{ OPC_TXS, "txs", 1, REG_X, REG_NONE, OF_NONE },
{ OPC_TYA, "tya", 1, REG_A, REG_A, OF_NONE },
/* Opcode description table */
const OPCDesc OPCTable[OPC_COUNT] = {
{ OPC_ADC, "adc", 0, REG_A, REG_A, OF_NONE },
{ OPC_AND, "and", 0, REG_A, REG_A, OF_NONE },
{ OPC_ASL, "asl", 0, REG_A, REG_A, OF_NONE },
{ OPC_BCC, "bcc", 2, REG_NONE, REG_NONE, OF_CBRA },
{ OPC_BCS, "bcs", 2, REG_NONE, REG_NONE, OF_CBRA },
{ OPC_BEQ, "beq", 2, REG_NONE, REG_NONE, OF_CBRA | OF_ZBRA },
{ OPC_BIT, "bit", 0, REG_A, REG_NONE, OF_NONE },
{ OPC_BMI, "bmi", 2, REG_NONE, REG_NONE, OF_CBRA },
{ OPC_BNE, "bne", 2, REG_NONE, REG_NONE, OF_CBRA | OF_ZBRA },
{ OPC_BPL, "bpl", 2, REG_NONE, REG_NONE, OF_CBRA },
{ OPC_BRA, "bra", 2, REG_NONE, REG_NONE, OF_UBRA },
{ OPC_BRK, "brk", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_BVC, "bvc", 2, REG_NONE, REG_NONE, OF_CBRA },
{ OPC_BVS, "bvs", 2, REG_NONE, REG_NONE, OF_CBRA },
{ OPC_CLC, "clc", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_CLD, "cld", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_CLI, "cli", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_CLV, "clv", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_CMP, "cmp", 0, REG_A, REG_NONE, OF_NONE },
{ OPC_CPX, "cpx", 0, REG_X, REG_NONE, OF_NONE },
{ OPC_CPY, "cpy", 0, REG_Y, REG_NONE, OF_NONE },
{ OPC_DEA, "dea", 1, REG_A, REG_A, OF_NONE },
{ OPC_DEC, "dec", 0, REG_NONE, REG_NONE, OF_NONE },
{ OPC_DEX, "dex", 1, REG_X, REG_X, OF_NONE },
{ OPC_DEY, "dey", 1, REG_Y, REG_Y, OF_NONE },
{ OPC_EOR, "eor", 0, REG_A, REG_A, OF_NONE },
{ OPC_INA, "ina", 1, REG_A, REG_A, OF_NONE },
{ OPC_INC, "inc", 0, REG_NONE, REG_NONE, OF_NONE },
{ OPC_INX, "inx", 1, REG_X, REG_X, OF_NONE },
{ OPC_INY, "iny", 1, REG_Y, REG_Y, OF_NONE },
{ OPC_JCC, "jcc", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
{ OPC_JCS, "jcs", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
{ OPC_JEQ, "jeq", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA | OF_ZBRA },
{ OPC_JMI, "jmi", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
{ OPC_JMP, "jmp", 3, REG_NONE, REG_NONE, OF_UBRA | OF_LBRA },
{ OPC_JNE, "jne", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA | OF_ZBRA },
{ OPC_JPL, "jpl", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
{ OPC_JSR, "jsr", 3, REG_NONE, REG_NONE, OF_NONE },
{ OPC_JVC, "jvc", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
{ OPC_JVS, "jvs", 5, REG_NONE, REG_NONE, OF_CBRA | OF_LBRA },
{ OPC_LDA, "lda", 0, REG_NONE, REG_A, OF_LOAD },
{ OPC_LDX, "ldx", 0, REG_NONE, REG_X, OF_LOAD },
{ OPC_LDY, "ldy", 0, REG_NONE, REG_Y, OF_LOAD },
{ OPC_LSR, "lsr", 0, REG_A, REG_A, OF_NONE },
{ OPC_NOP, "nop", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_ORA, "ora", 0, REG_A, REG_A, OF_NONE },
{ OPC_PHA, "pha", 1, REG_A, REG_NONE, OF_NONE },
{ OPC_PHP, "php", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_PHX, "phx", 1, REG_X, REG_NONE, OF_NONE },
{ OPC_PHY, "phy", 1, REG_Y, REG_NONE, OF_NONE },
{ OPC_PLA, "pla", 1, REG_NONE, REG_A, OF_NONE },
{ OPC_PLP, "plp", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_PLX, "plx", 1, REG_NONE, REG_X, OF_NONE },
{ OPC_PLY, "ply", 1, REG_NONE, REG_Y, OF_NONE },
{ OPC_ROL, "rol", 0, REG_A, REG_A, OF_NONE },
{ OPC_ROR, "ror", 0, REG_A, REG_A, OF_NONE },
{ OPC_RTI, "rti", 1, REG_NONE, REG_NONE, OF_RET },
{ OPC_RTS, "rts", 1, REG_NONE, REG_NONE, OF_RET },
{ OPC_SBC, "sbc", 0, REG_A, REG_A, OF_NONE },
{ OPC_SEC, "sec", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_SED, "sed", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_SEI, "sei", 1, REG_NONE, REG_NONE, OF_NONE },
{ OPC_STA, "sta", 0, REG_A, REG_NONE, OF_NONE },
{ OPC_STX, "stx", 0, REG_X, REG_NONE, OF_NONE },
{ OPC_STY, "sty", 0, REG_Y, REG_NONE, OF_NONE },
{ OPC_TAX, "tax", 1, REG_A, REG_X, OF_NONE },
{ OPC_TAY, "tay", 1, REG_A, REG_Y, OF_NONE },
{ OPC_TRB, "trb", 0, REG_A, REG_NONE, OF_NONE },
{ OPC_TSB, "tsb", 0, REG_A, REG_NONE, OF_NONE },
{ OPC_TSX, "tsx", 1, REG_NONE, REG_X, OF_NONE },
{ OPC_TXA, "txa", 1, REG_X, REG_A, OF_NONE },
{ OPC_TXS, "txs", 1, REG_X, REG_NONE, OF_NONE },
{ OPC_TYA, "tya", 1, REG_A, REG_A, OF_NONE },
};
@ -203,30 +203,6 @@ unsigned GetInsnSize (opc_t OPC, am_t AM)
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];
}
unsigned char GetOPCInfo (opc_t OPC)
/* Get opcode information */
{
/* Check the range */
PRECONDITION (OPC >= (opc_t)0 && OPC < OPC_COUNT);
/* Return the info */
return OPCTable[OPC].Info;
}
unsigned char GetAMUseInfo (am_t AM)
/* Get usage info for the given addressing mode (addressing modes that use
* index registers return REG_r info for these registers).

View File

@ -38,6 +38,11 @@
/* common */
#include "inline.h"
/*****************************************************************************/
/* Data */
/*****************************************************************************/
@ -155,7 +160,8 @@ typedef enum {
#define OF_NONE 0x0000U /* No additional information */
#define OF_UBRA 0x0001U /* Unconditional branch */
#define OF_CBRA 0x0002U /* Conditional branch */
#define OF_LBRA 0x0004U /* Jump/branch is long */
#define OF_ZBRA 0x0004U /* Branch on zero flag condition */
#define OF_LBRA 0x0008U /* Jump/branch is long */
#define OF_RET 0x0010U /* Return from function */
#define OF_LOAD 0x0020U /* Register load */
#define OF_BRA (OF_UBRA|OF_CBRA) /* Operation is a jump/branch */
@ -171,6 +177,9 @@ typedef struct {
unsigned char Info; /* Additional information */
} OPCDesc;
/* Opcode description table */
extern const OPCDesc OPCTable[OPC_COUNT];
/*****************************************************************************/
@ -187,11 +196,27 @@ const OPCDesc* FindOpcode (const char* OPC);
unsigned GetInsnSize (opc_t OPC, am_t AM);
/* Return the size of the given instruction */
const OPCDesc* GetOPCDesc (opc_t OPC);
#if defined(HAVE_INLINE)
INLINE const OPCDesc* GetOPCDesc (opc_t OPC)
/* Get an opcode description */
{
/* Return the description */
return &OPCTable [OPC];
}
#else
# define GetOPCDesc(OPC) (&OPCTable [(OPC)])
#endif
unsigned char GetOPCInfo (opc_t OPC);
#if defined(HAVE_INLINE)
INLINE unsigned char GetOPCInfo (opc_t OPC)
/* Get opcode information */
{
/* Return the info */
return OPCTable[OPC].Info;
}
#else
# define GetOPCInfo(OPC) (OPCTable[(OPC)].Info)
#endif
unsigned char GetAMUseInfo (am_t AM);
/* Get usage info for the given addressing mode (addressing modes that use