mirror of
https://github.com/cc65/cc65.git
synced 2025-08-08 06:25:17 +00:00
Working on the new backend
git-svn-id: svn://svn.cc65.org/cc65/trunk@710 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
@@ -39,6 +39,7 @@
|
|||||||
|
|
||||||
/* cc65 */
|
/* cc65 */
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
/* b6502 */
|
/* b6502 */
|
||||||
#include "codeinfo.h"
|
#include "codeinfo.h"
|
||||||
@@ -71,9 +72,10 @@ CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, CodeLabel* JumpTo)
|
|||||||
E->AM = AM;
|
E->AM = AM;
|
||||||
E->Size = GetInsnSize (E->OPC, E->AM);
|
E->Size = GetInsnSize (E->OPC, E->AM);
|
||||||
E->Hints = 0;
|
E->Hints = 0;
|
||||||
E->Arg.Num = 0;
|
E->Arg = 0;
|
||||||
|
E->Num = 0;
|
||||||
E->Flags = 0;
|
E->Flags = 0;
|
||||||
E->Usage = D->Info & (CI_MASK_USE | CI_MASK_CHG);
|
E->Info = D->Info | GetAMUseInfo (AM);
|
||||||
E->JumpTo = JumpTo;
|
E->JumpTo = JumpTo;
|
||||||
InitCollection (&E->Labels);
|
InitCollection (&E->Labels);
|
||||||
|
|
||||||
@@ -91,7 +93,8 @@ CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, CodeLabel* JumpTo)
|
|||||||
void FreeCodeEntry (CodeEntry* E)
|
void FreeCodeEntry (CodeEntry* E)
|
||||||
/* Free the given code entry */
|
/* Free the given code entry */
|
||||||
{
|
{
|
||||||
/* ## Free the string argument if we have one */
|
/* Free the string argument if we have one */
|
||||||
|
xfree (E->Arg);
|
||||||
|
|
||||||
/* Cleanup the collection */
|
/* Cleanup the collection */
|
||||||
DoneCollection (&E->Labels);
|
DoneCollection (&E->Labels);
|
||||||
@@ -102,77 +105,86 @@ void FreeCodeEntry (CodeEntry* E)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int CodeEntryHasLabel (const CodeEntry* E)
|
||||||
|
/* Check if the given code entry has labels attached */
|
||||||
|
{
|
||||||
|
return (CollCount (&E->Labels) > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void OutputCodeEntry (FILE* F, const CodeEntry* E)
|
void OutputCodeEntry (FILE* F, const CodeEntry* E)
|
||||||
/* Output the code entry to a file */
|
/* Output the code entry to a file */
|
||||||
{
|
{
|
||||||
const OPCDesc* D;
|
const OPCDesc* D;
|
||||||
|
unsigned Chars;
|
||||||
|
|
||||||
/* If we have a label, print that */
|
/* If we have a label, print that */
|
||||||
unsigned LabelCount = CollCount (&E->Labels);
|
unsigned LabelCount = CollCount (&E->Labels);
|
||||||
unsigned I;
|
unsigned I;
|
||||||
for (I = 0; I < LabelCount; ++I) {
|
for (I = 0; I < LabelCount; ++I) {
|
||||||
OutputCodeLabel (F, CollConstAt (&E->Labels, I));
|
OutputCodeLabel (F, CollConstAt (&E->Labels, I));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the opcode description */
|
/* Get the opcode description */
|
||||||
D = GetOPCDesc (E->OPC);
|
D = GetOPCDesc (E->OPC);
|
||||||
|
|
||||||
/* Print the mnemonic */
|
/* Print the mnemonic */
|
||||||
fprintf (F, "\t%s", D->Mnemo);
|
Chars = fprintf (F, "\t%s", D->Mnemo);
|
||||||
|
|
||||||
/* Print the operand */
|
/* Print the operand */
|
||||||
switch (E->AM) {
|
switch (E->AM) {
|
||||||
|
|
||||||
case AM_IMP:
|
case AM_IMP:
|
||||||
/* implicit */
|
/* implicit */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AM_ACC:
|
case AM_ACC:
|
||||||
/* accumulator */
|
/* accumulator */
|
||||||
fprintf (F, "\ta");
|
Chars += fprintf (F, "%*sa", 9-Chars, "");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AM_IMM:
|
case AM_IMM:
|
||||||
/* immidiate */
|
/* immidiate */
|
||||||
fprintf (F, "\t#%s", E->Arg.Expr);
|
Chars += fprintf (F, "%*s#%s", 9-Chars, "", E->Arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AM_ZP:
|
case AM_ZP:
|
||||||
case AM_ABS:
|
case AM_ABS:
|
||||||
/* zeropage and absolute */
|
/* zeropage and absolute */
|
||||||
fprintf (F, "\t%s", E->Arg.Expr);
|
Chars += fprintf (F, "%*s%s", 9-Chars, "", E->Arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AM_ZPX:
|
case AM_ZPX:
|
||||||
case AM_ABSX:
|
case AM_ABSX:
|
||||||
/* zeropage,X and absolute,X */
|
/* zeropage,X and absolute,X */
|
||||||
fprintf (F, "\t%s,x", E->Arg.Expr);
|
Chars += fprintf (F, "%*s%s,x", 9-Chars, "", E->Arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AM_ABSY:
|
case AM_ABSY:
|
||||||
/* absolute,Y */
|
/* absolute,Y */
|
||||||
fprintf (F, "\t%s,y", E->Arg.Expr);
|
Chars += fprintf (F, "%*s%s,y", 9-Chars, "", E->Arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AM_ZPX_IND:
|
case AM_ZPX_IND:
|
||||||
/* (zeropage,x) */
|
/* (zeropage,x) */
|
||||||
fprintf (F, "\t(%s,x)", E->Arg.Expr);
|
Chars += fprintf (F, "%*s(%s,x)", 9-Chars, "", E->Arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AM_ZP_INDY:
|
case AM_ZP_INDY:
|
||||||
/* (zeropage),y */
|
/* (zeropage),y */
|
||||||
fprintf (F, "\t(%s),y", E->Arg.Expr);
|
Chars += fprintf (F, "%*s(%s),y", 9-Chars, "", E->Arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AM_ZP_IND:
|
case AM_ZP_IND:
|
||||||
/* (zeropage) */
|
/* (zeropage) */
|
||||||
fprintf (F, "\t(%s)", E->Arg.Expr);
|
Chars += fprintf (F, "%*s(%s)", 9-Chars, "", E->Arg);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AM_BRA:
|
case AM_BRA:
|
||||||
/* branch */
|
/* branch */
|
||||||
CHECK (E->JumpTo != 0);
|
CHECK (E->JumpTo != 0);
|
||||||
fprintf (F, "\t%s", E->JumpTo->Name);
|
Chars += fprintf (F, "%*s%s", 9-Chars, "", E->JumpTo->Name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -180,6 +192,19 @@ void OutputCodeEntry (FILE* F, const CodeEntry* E)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Print usage info if requested by the debugging flag */
|
||||||
|
// if (Debug) {
|
||||||
|
Chars += fprintf (F,
|
||||||
|
"%*s; USE: %c%c%c CHG: %c%c%c",
|
||||||
|
30-Chars, "",
|
||||||
|
(E->Info & CI_USE_A)? 'A' : '_',
|
||||||
|
(E->Info & CI_USE_X)? 'X' : '_',
|
||||||
|
(E->Info & CI_USE_Y)? 'Y' : '_',
|
||||||
|
(E->Info & CI_CHG_A)? 'A' : '_',
|
||||||
|
(E->Info & CI_CHG_X)? 'X' : '_',
|
||||||
|
(E->Info & CI_CHG_Y)? 'Y' : '_');
|
||||||
|
// }
|
||||||
|
|
||||||
/* Terminate the line */
|
/* Terminate the line */
|
||||||
fprintf (F, "\n");
|
fprintf (F, "\n");
|
||||||
}
|
}
|
||||||
|
@@ -55,6 +55,10 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Flags used */
|
||||||
|
#define CEF_USERMARK 0x0001U /* Generic mark by user functions */
|
||||||
|
#define CEF_NUMARG 0x0002U /* Insn has numerical argument */
|
||||||
|
|
||||||
/* Code entry structure */
|
/* Code entry structure */
|
||||||
typedef struct CodeEntry CodeEntry;
|
typedef struct CodeEntry CodeEntry;
|
||||||
struct CodeEntry {
|
struct CodeEntry {
|
||||||
@@ -62,12 +66,10 @@ struct CodeEntry {
|
|||||||
am_t AM; /* Adressing mode */
|
am_t AM; /* Adressing mode */
|
||||||
unsigned char Size; /* Estimated size */
|
unsigned char Size; /* Estimated size */
|
||||||
unsigned char Hints; /* Hints for this entry */
|
unsigned char Hints; /* Hints for this entry */
|
||||||
union {
|
char* Arg; /* Argument as string */
|
||||||
unsigned Num; /* Numeric argument */
|
unsigned Num; /* Numeric argument */
|
||||||
char* Expr; /* Textual argument */
|
|
||||||
} Arg;
|
|
||||||
unsigned short Flags; /* Flags */
|
unsigned short Flags; /* Flags */
|
||||||
unsigned short Usage; /* Register usage for this entry */
|
unsigned short Info; /* Register usage info for this entry */
|
||||||
CodeLabel* JumpTo; /* Jump label */
|
CodeLabel* JumpTo; /* Jump label */
|
||||||
Collection Labels; /* Labels for this instruction */
|
Collection Labels; /* Labels for this instruction */
|
||||||
};
|
};
|
||||||
@@ -86,6 +88,9 @@ CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, CodeLabel* JumpTo);
|
|||||||
void FreeCodeEntry (CodeEntry* E);
|
void FreeCodeEntry (CodeEntry* E);
|
||||||
/* Free the given code entry */
|
/* Free the given code entry */
|
||||||
|
|
||||||
|
int CodeEntryHasLabel (const CodeEntry* E);
|
||||||
|
/* Check if the given code entry has labels attached */
|
||||||
|
|
||||||
void OutputCodeEntry (FILE* F, const CodeEntry* E);
|
void OutputCodeEntry (FILE* F, const CodeEntry* E);
|
||||||
/* Output the code entry to a file */
|
/* Output the code entry to a file */
|
||||||
|
|
||||||
|
@@ -36,7 +36,8 @@
|
|||||||
/* common */
|
/* common */
|
||||||
#include "xmalloc.h"
|
#include "xmalloc.h"
|
||||||
|
|
||||||
/* cc65 */
|
/* b6502 */
|
||||||
|
#include "codeent.h"
|
||||||
#include "label.h"
|
#include "label.h"
|
||||||
|
|
||||||
|
|
||||||
@@ -82,6 +83,18 @@ void FreeCodeLabel (CodeLabel* L)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void AddLabelRef (CodeLabel* L, struct CodeEntry* E)
|
||||||
|
/* Let the CodeEntry E reference the label L */
|
||||||
|
{
|
||||||
|
/* The insn at E jumps to this label */
|
||||||
|
E->JumpTo = L;
|
||||||
|
|
||||||
|
/* Remember that in the label */
|
||||||
|
CollAppend (&L->JumpFrom, E);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E)
|
unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E)
|
||||||
/* Remove a reference to this label, return the number of remaining references */
|
/* Remove a reference to this label, return the number of remaining references */
|
||||||
{
|
{
|
||||||
@@ -97,7 +110,7 @@ unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E)
|
|||||||
void OutputCodeLabel (FILE* F, const CodeLabel* L)
|
void OutputCodeLabel (FILE* F, const CodeLabel* L)
|
||||||
/* Output the code label to a file */
|
/* Output the code label to a file */
|
||||||
{
|
{
|
||||||
fprintf (F, "%s:\n", L->Name);
|
fprintf (F, "%s:", L->Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -89,6 +89,9 @@ CodeLabel* NewCodeLabel (const char* Name, unsigned Hash);
|
|||||||
void FreeCodeLabel (CodeLabel* L);
|
void FreeCodeLabel (CodeLabel* L);
|
||||||
/* Free the given code label */
|
/* Free the given code label */
|
||||||
|
|
||||||
|
void AddLabelRef (CodeLabel* L, struct CodeEntry* E);
|
||||||
|
/* Let the CodeEntry E reference the label L */
|
||||||
|
|
||||||
unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E);
|
unsigned RemoveLabelRef (CodeLabel* L, const struct CodeEntry* E);
|
||||||
/* Remove a reference to this label, return the number of remaining references */
|
/* Remove a reference to this label, return the number of remaining references */
|
||||||
|
|
||||||
|
@@ -33,14 +33,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* common */
|
||||||
|
#include "print.h"
|
||||||
|
|
||||||
|
/* cc65 */
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
/* b6502 */
|
/* b6502 */
|
||||||
#include "codeent.h"
|
#include "codeent.h"
|
||||||
|
#include "codeinfo.h"
|
||||||
#include "codeopt.h"
|
#include "codeopt.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Data */
|
/* Data */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
@@ -53,7 +60,7 @@ static unsigned OptChanges;
|
|||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Remove dead jumps */
|
/* Remove dead jumps */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
@@ -80,34 +87,15 @@ static void OptDeadJumps (CodeSeg* S)
|
|||||||
/* Check if it's a branch, if it has a local target, and if the target
|
/* Check if it's a branch, if it has a local target, and if the target
|
||||||
* is the next instruction.
|
* is the next instruction.
|
||||||
*/
|
*/
|
||||||
if (E->AM == AM_BRA) {
|
|
||||||
printf ("BRA on entry %u:\n", I);
|
|
||||||
if (E->JumpTo) {
|
|
||||||
printf (" JumpTo ok\n");
|
|
||||||
if (E->JumpTo->Owner == CollAt (&S->Entries, I+1)) {
|
|
||||||
printf (" Branch to next insn\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (E->AM == AM_BRA && E->JumpTo && E->JumpTo->Owner == CollAt (&S->Entries, I+1)) {
|
if (E->AM == AM_BRA && E->JumpTo && E->JumpTo->Owner == CollAt (&S->Entries, I+1)) {
|
||||||
|
|
||||||
/* Remember the label */
|
/* Delete the dead jump */
|
||||||
CodeLabel* L = E->JumpTo;
|
DelCodeSegLine (S, I);
|
||||||
|
|
||||||
/* Jump to next instruction, remove it */
|
/* Keep the number of entries updated */
|
||||||
unsigned Remaining = RemoveLabelRef (L, E);
|
|
||||||
CollDelete (&S->Entries, I);
|
|
||||||
FreeCodeEntry (E);
|
|
||||||
--Count;
|
--Count;
|
||||||
|
|
||||||
/* If the label has no more references, remove it */
|
/* Remember, we had changes */
|
||||||
if (Remaining == 0) {
|
|
||||||
CollDeleteItem (&L->Owner->Labels, L);
|
|
||||||
FreeCodeLabel (L);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remember we had changes */
|
|
||||||
++OptChanges;
|
++OptChanges;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -121,6 +109,131 @@ static void OptDeadJumps (CodeSeg* S)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Remove dead code */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void OptDeadCode (CodeSeg* S)
|
||||||
|
/* Remove dead code (code that follows an unconditional jump or an rts/rti
|
||||||
|
* and has no label)
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
unsigned I;
|
||||||
|
|
||||||
|
/* Get the number of entries, bail out if we have less than two entries */
|
||||||
|
unsigned Count = CollCount (&S->Entries);
|
||||||
|
if (Count < 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Walk over all entries minus the last one */
|
||||||
|
I = 0;
|
||||||
|
while (I < Count-1) {
|
||||||
|
|
||||||
|
/* Get this entry */
|
||||||
|
CodeEntry* E = CollAt (&S->Entries, I);
|
||||||
|
|
||||||
|
/* Check if it's an unconditional branch, and if the next entry has
|
||||||
|
* no labels attached
|
||||||
|
*/
|
||||||
|
if ((E->OPC == OPC_JMP || E->OPC == OPC_BRA || E->OPC == OPC_RTS || E->OPC == OPC_RTI) &&
|
||||||
|
!CodeEntryHasLabel (CollAt (&S->Entries, I+1))) {
|
||||||
|
|
||||||
|
/* Delete the next entry */
|
||||||
|
DelCodeSegLine (S, I+1);
|
||||||
|
|
||||||
|
/* Keep the number of entries updated */
|
||||||
|
--Count;
|
||||||
|
|
||||||
|
/* Remember, we had changes */
|
||||||
|
++OptChanges;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
/* Next entry */
|
||||||
|
++I;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* Optimize jump cascades */
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void OptJumpCascades (CodeSeg* S)
|
||||||
|
/* Optimize jump cascades (jumps to jumps). In such a case, the jump is
|
||||||
|
* replaced by a jump to the final location. This will in some cases produce
|
||||||
|
* worse code, because some jump targets are no longer reachable by short
|
||||||
|
* branches, but this is quite rare, so there are more advantages than
|
||||||
|
* disadvantages.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
unsigned I;
|
||||||
|
|
||||||
|
/* Get the number of entries, bail out if we have no entries */
|
||||||
|
unsigned Count = CollCount (&S->Entries);
|
||||||
|
if (Count == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Walk over all entries */
|
||||||
|
I = 0;
|
||||||
|
while (I < Count) {
|
||||||
|
|
||||||
|
CodeLabel* OldLabel;
|
||||||
|
CodeLabel* NewLabel;
|
||||||
|
|
||||||
|
/* Get this entry */
|
||||||
|
CodeEntry* E = CollAt (&S->Entries, I);
|
||||||
|
|
||||||
|
/* Check if it's a branch, if it has a label attached, and if the
|
||||||
|
* instruction at this label is also a branch.
|
||||||
|
*/
|
||||||
|
if (E->AM == AM_BRA &&
|
||||||
|
(OldLabel = E->JumpTo) != 0 &&
|
||||||
|
OldLabel->Owner->AM == AM_BRA &&
|
||||||
|
(NewLabel = OldLabel->Owner->JumpTo) != 0) {
|
||||||
|
|
||||||
|
/* Get the instruction that has the new label attached */
|
||||||
|
CodeEntry* N = OldLabel->Owner;
|
||||||
|
|
||||||
|
/* Remove the reference to our label and delete it if this was
|
||||||
|
* the last reference.
|
||||||
|
*/
|
||||||
|
if (RemoveLabelRef (OldLabel, E) == 0) {
|
||||||
|
/* Delete it */
|
||||||
|
DelCodeLabel (S, OldLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove usage information from the entry and use the usage
|
||||||
|
* information from the new instruction instead.
|
||||||
|
*/
|
||||||
|
E->Info &= ~(CI_MASK_USE | CI_MASK_CHG);
|
||||||
|
E->Info |= N->Info & ~(CI_MASK_USE | CI_MASK_CHG);
|
||||||
|
|
||||||
|
/* Use the new label */
|
||||||
|
AddLabelRef (NewLabel, E);
|
||||||
|
|
||||||
|
/* Remember ,we had changes */
|
||||||
|
++OptChanges;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Next entry */
|
||||||
|
++I;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/* Code */
|
/* Code */
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@@ -130,15 +243,34 @@ static void OptDeadJumps (CodeSeg* S)
|
|||||||
void RunOpt (CodeSeg* S)
|
void RunOpt (CodeSeg* S)
|
||||||
/* Run the optimizer */
|
/* Run the optimizer */
|
||||||
{
|
{
|
||||||
printf ("Optimize\n");
|
typedef void (*OptFunc) (CodeSeg*);
|
||||||
|
|
||||||
|
/* Table with optimizer steps - are called in this order */
|
||||||
|
static const OptFunc OptFuncs [] = {
|
||||||
|
OptJumpCascades, /* Optimize jump cascades */
|
||||||
|
OptDeadJumps, /* Remove dead jumps */
|
||||||
|
OptDeadCode, /* Remove dead code */
|
||||||
|
};
|
||||||
|
|
||||||
/* Repeat all steps until there are no more changes */
|
/* Repeat all steps until there are no more changes */
|
||||||
do {
|
do {
|
||||||
|
|
||||||
|
unsigned long Flags;
|
||||||
|
unsigned I;
|
||||||
|
|
||||||
/* Reset the number of changes */
|
/* Reset the number of changes */
|
||||||
OptChanges = 0;
|
OptChanges = 0;
|
||||||
|
|
||||||
OptDeadJumps (S);
|
/* Run all optimization steps */
|
||||||
|
Flags = 1UL;
|
||||||
|
for (I = 0; I < sizeof(OptFuncs)/sizeof(OptFuncs[0]); ++I) {
|
||||||
|
if ((OptDisable & Flags) == 0) {
|
||||||
|
OptFuncs[I] (S);
|
||||||
|
} else if (Verbosity > 0 || Debug) {
|
||||||
|
printf ("Optimizer pass %u skipped\n", I);
|
||||||
|
}
|
||||||
|
Flags <<= 1;
|
||||||
|
}
|
||||||
|
|
||||||
} while (OptChanges > 0);
|
} while (OptChanges > 0);
|
||||||
}
|
}
|
||||||
|
@@ -136,10 +136,10 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
|
|||||||
* white space, for example.
|
* white space, for example.
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
char Mnemo[16];
|
char Mnemo[16];
|
||||||
const OPCDesc* OPC;
|
const OPCDesc* OPC;
|
||||||
am_t AM = 0; /* Initialize to keep gcc silent */
|
am_t AM = 0; /* Initialize to keep gcc silent */
|
||||||
char Expr[64];
|
char Arg[64];
|
||||||
char Reg;
|
char Reg;
|
||||||
CodeEntry* E;
|
CodeEntry* E;
|
||||||
CodeLabel* Label;
|
CodeLabel* Label;
|
||||||
@@ -160,7 +160,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
|
|||||||
L = SkipSpace (L);
|
L = SkipSpace (L);
|
||||||
|
|
||||||
/* Get the addressing mode */
|
/* Get the addressing mode */
|
||||||
Expr[0] = '\0';
|
Arg[0] = '\0';
|
||||||
switch (*L) {
|
switch (*L) {
|
||||||
|
|
||||||
case '\0':
|
case '\0':
|
||||||
@@ -170,13 +170,13 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
|
|||||||
|
|
||||||
case '#':
|
case '#':
|
||||||
/* Immidiate */
|
/* Immidiate */
|
||||||
StrCopy (Expr, sizeof (Expr), L+1);
|
StrCopy (Arg, sizeof (Arg), L+1);
|
||||||
AM = AM_IMM;
|
AM = AM_IMM;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '(':
|
case '(':
|
||||||
/* Indirect */
|
/* Indirect */
|
||||||
L = ReadToken (L+1, ",)", Expr, sizeof (Expr));
|
L = ReadToken (L+1, ",)", Arg, sizeof (Arg));
|
||||||
|
|
||||||
/* Check for errors */
|
/* Check for errors */
|
||||||
if (*L == '\0') {
|
if (*L == '\0') {
|
||||||
@@ -214,7 +214,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
|
|||||||
}
|
}
|
||||||
L = SkipSpace (L+1);
|
L = SkipSpace (L+1);
|
||||||
if (*L != '\0') {
|
if (*L != '\0') {
|
||||||
Error ("ASM code error: syntax error");
|
Error ("ASM code error: syntax error");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
AM = AM_ZP_INDY;
|
AM = AM_ZP_INDY;
|
||||||
@@ -238,7 +238,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
/* Absolute, maybe indexed */
|
/* Absolute, maybe indexed */
|
||||||
L = ReadToken (L, ",", Expr, sizeof (Expr));
|
L = ReadToken (L, ",", Arg, sizeof (Arg));
|
||||||
if (*L == '\0') {
|
if (*L == '\0') {
|
||||||
/* Assume absolute */
|
/* Assume absolute */
|
||||||
AM = AM_ABS;
|
AM = AM_ABS;
|
||||||
@@ -257,7 +257,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
|
|||||||
AM = AM_ABSY;
|
AM = AM_ABSY;
|
||||||
} else {
|
} else {
|
||||||
Error ("ASM code error: syntax error");
|
Error ("ASM code error: syntax error");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (*L != '\0') {
|
if (*L != '\0') {
|
||||||
Error ("ASM code error: syntax error");
|
Error ("ASM code error: syntax error");
|
||||||
@@ -273,7 +273,7 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
|
|||||||
* if it does not exist. Ignore anything but local labels here.
|
* if it does not exist. Ignore anything but local labels here.
|
||||||
*/
|
*/
|
||||||
Label = 0;
|
Label = 0;
|
||||||
if ((OPC->Info & CI_MASK_BRA) == CI_BRA && Expr[0] == 'L') {
|
if ((OPC->Info & CI_MASK_BRA) == CI_BRA && Arg[0] == 'L') {
|
||||||
|
|
||||||
unsigned Hash;
|
unsigned Hash;
|
||||||
|
|
||||||
@@ -284,13 +284,13 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
|
|||||||
AM = AM_BRA;
|
AM = AM_BRA;
|
||||||
|
|
||||||
/* Generate the hash over the label, then search for the label */
|
/* Generate the hash over the label, then search for the label */
|
||||||
Hash = HashStr (Expr) % CS_LABEL_HASH_SIZE;
|
Hash = HashStr (Arg) % CS_LABEL_HASH_SIZE;
|
||||||
Label = FindCodeLabel (S, Expr, Hash);
|
Label = FindCodeLabel (S, Arg, Hash);
|
||||||
|
|
||||||
/* If we don't have the label, it's a forward ref - create it */
|
/* If we don't have the label, it's a forward ref - create it */
|
||||||
if (Label == 0) {
|
if (Label == 0) {
|
||||||
/* Generate a new label */
|
/* Generate a new label */
|
||||||
Label = NewCodeSegLabel (S, Expr, Hash);
|
Label = NewCodeSegLabel (S, Arg, Hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,9 +298,9 @@ static CodeEntry* ParseInsn (CodeSeg* S, const char* L)
|
|||||||
* structure and initialize it.
|
* structure and initialize it.
|
||||||
*/
|
*/
|
||||||
E = NewCodeEntry (OPC, AM, Label);
|
E = NewCodeEntry (OPC, AM, Label);
|
||||||
if (Expr[0] != '\0') {
|
if (Arg[0] != '\0') {
|
||||||
/* We have an additional expression */
|
/* We have an additional expression */
|
||||||
E->Arg.Expr = xstrdup (Expr);
|
E->Arg = xstrdup (Arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the new code entry */
|
/* Return the new code entry */
|
||||||
@@ -342,34 +342,7 @@ CodeSeg* NewCodeSeg (const char* SegName, const char* FuncName)
|
|||||||
void FreeCodeSeg (CodeSeg* S)
|
void FreeCodeSeg (CodeSeg* S)
|
||||||
/* Free a code segment including all code entries */
|
/* Free a code segment including all code entries */
|
||||||
{
|
{
|
||||||
unsigned I, Count;
|
FAIL ("Not implemented");
|
||||||
|
|
||||||
/* Free the names */
|
|
||||||
xfree (S->SegName);
|
|
||||||
xfree (S->FuncName);
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -422,7 +395,7 @@ void AddCodeSegLine (CodeSeg* S, const char* Format, ...)
|
|||||||
E = 0; /* Assume no insn created */
|
E = 0; /* Assume no insn created */
|
||||||
switch (*L) {
|
switch (*L) {
|
||||||
|
|
||||||
case '\0':
|
case '\0':
|
||||||
/* Empty line, just ignore it */
|
/* Empty line, just ignore it */
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -469,6 +442,45 @@ void AddCodeSegLine (CodeSeg* S, const char* Format, ...)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void DelCodeSegLine (CodeSeg* S, unsigned Index)
|
||||||
|
/* Delete an entry from the code segment. This includes deleting any associated
|
||||||
|
* labels, removing references to labels and even removing the referenced labels
|
||||||
|
* if the reference count drops to zero.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* Get the code entry for the given index */
|
||||||
|
CodeEntry* E = CollAt (&S->Entries, Index);
|
||||||
|
|
||||||
|
/* Remove any labels associated with this entry */
|
||||||
|
unsigned Count;
|
||||||
|
while ((Count = CollCount (&E->Labels)) > 0) {
|
||||||
|
DelCodeLabel (S, CollAt (&E->Labels, Count-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If this insn references a label, remove the reference. And, if the
|
||||||
|
* the reference count for this label drops to zero, remove this label.
|
||||||
|
*/
|
||||||
|
if (E->JumpTo) {
|
||||||
|
|
||||||
|
/* Remove the reference */
|
||||||
|
if (RemoveLabelRef (E->JumpTo, E) == 0) {
|
||||||
|
/* No references remaining, remove the label */
|
||||||
|
DelCodeLabel (S, E->JumpTo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset the label pointer to avoid problems later */
|
||||||
|
E->JumpTo = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Delete the pointer to the insn */
|
||||||
|
CollDelete (&S->Entries, Index);
|
||||||
|
|
||||||
|
/* Delete the instruction itself */
|
||||||
|
FreeCodeEntry (E);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AddCodeLabel (CodeSeg* S, const char* Name)
|
void AddCodeLabel (CodeSeg* S, const char* Name)
|
||||||
/* Add a code label for the next instruction to follow */
|
/* Add a code label for the next instruction to follow */
|
||||||
{
|
{
|
||||||
@@ -480,11 +492,11 @@ void AddCodeLabel (CodeSeg* S, const char* Name)
|
|||||||
|
|
||||||
/* Did we find it? */
|
/* Did we find it? */
|
||||||
if (L) {
|
if (L) {
|
||||||
/* We found it - be sure it does not already have an owner */
|
/* We found it - be sure it does not already have an owner */
|
||||||
CHECK (L->Owner == 0);
|
CHECK (L->Owner == 0);
|
||||||
} else {
|
} else {
|
||||||
/* Not found - create a new one */
|
/* Not found - create a new one */
|
||||||
L = NewCodeSegLabel (S, Name, Hash);
|
L = NewCodeSegLabel (S, Name, Hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We do now have a valid label. Remember it for later */
|
/* We do now have a valid label. Remember it for later */
|
||||||
@@ -493,6 +505,49 @@ void AddCodeLabel (CodeSeg* S, const char* Name)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void DelCodeLabel (CodeSeg* S, CodeLabel* L)
|
||||||
|
/* Remove references from this label and delete it. */
|
||||||
|
{
|
||||||
|
unsigned Count, I;
|
||||||
|
|
||||||
|
/* Get the first entry in the hash chain */
|
||||||
|
CodeLabel* List = S->LabelHash[L->Hash];
|
||||||
|
|
||||||
|
/* First, remove the label from the hash chain */
|
||||||
|
if (List == L) {
|
||||||
|
/* First entry in hash chain */
|
||||||
|
S->LabelHash[L->Hash] = L->Next;
|
||||||
|
} else {
|
||||||
|
/* Must search through the chain */
|
||||||
|
while (List->Next != L) {
|
||||||
|
/* If we've reached the end of the chain, something is *really* wrong */
|
||||||
|
CHECK (List->Next != 0);
|
||||||
|
/* Next entry */
|
||||||
|
List = List->Next;
|
||||||
|
}
|
||||||
|
/* The next entry is the one, we have been searching for */
|
||||||
|
List->Next = L->Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Remove references from insns jumping to this label */
|
||||||
|
Count = CollCount (&L->JumpFrom);
|
||||||
|
for (I = 0; I < Count; ++I) {
|
||||||
|
/* Get the insn referencing this label */
|
||||||
|
CodeEntry* E = CollAt (&L->JumpFrom, I);
|
||||||
|
/* Remove the reference */
|
||||||
|
E->JumpTo = 0;
|
||||||
|
}
|
||||||
|
CollDeleteAll (&L->JumpFrom);
|
||||||
|
|
||||||
|
/* Remove the reference to the owning instruction */
|
||||||
|
CollDeleteItem (&L->Owner->Labels, L);
|
||||||
|
|
||||||
|
/* All references removed, delete the label itself */
|
||||||
|
FreeCodeLabel (L);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void AddCodeSegHint (CodeSeg* S, unsigned Hint)
|
void AddCodeSegHint (CodeSeg* S, unsigned Hint)
|
||||||
/* Add a hint for the preceeding instruction */
|
/* Add a hint for the preceeding instruction */
|
||||||
{
|
{
|
||||||
@@ -551,6 +606,16 @@ void OutputCodeSeg (FILE* F, const CodeSeg* S)
|
|||||||
/* Get the number of entries in this segment */
|
/* Get the number of entries in this segment */
|
||||||
unsigned Count = CollCount (&S->Entries);
|
unsigned Count = CollCount (&S->Entries);
|
||||||
|
|
||||||
|
fprintf (F, "; Labels: ");
|
||||||
|
for (I = 0; I < CS_LABEL_HASH_SIZE; ++I) {
|
||||||
|
const CodeLabel* L = S->LabelHash[I];
|
||||||
|
while (L) {
|
||||||
|
fprintf (F, "%s ", L->Name);
|
||||||
|
L = L->Next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fprintf (F, "\n");
|
||||||
|
|
||||||
/* Output the segment directive */
|
/* Output the segment directive */
|
||||||
fprintf (F, ".segment\t\"%s\"\n\n", S->SegName);
|
fprintf (F, ".segment\t\"%s\"\n\n", S->SegName);
|
||||||
|
|
||||||
@@ -633,19 +698,20 @@ void MergeCodeLabels (CodeSeg* S)
|
|||||||
unsigned RefCount = CollCount (&L->JumpFrom);
|
unsigned RefCount = CollCount (&L->JumpFrom);
|
||||||
for (K = 0; K < RefCount; ++K) {
|
for (K = 0; K < RefCount; ++K) {
|
||||||
|
|
||||||
/* Get the next instrcuction that references this label */
|
/* Get the next instruction that references this label */
|
||||||
CodeEntry* E = CollAt (&L->JumpFrom, K);
|
CodeEntry* E = CollAt (&L->JumpFrom, K);
|
||||||
|
|
||||||
/* Change the reference */
|
/* Change the reference */
|
||||||
CHECK (E->JumpTo == L);
|
CHECK (E->JumpTo == L);
|
||||||
E->JumpTo = RefLab;
|
AddLabelRef (RefLab, E);
|
||||||
CollAppend (&RefLab->JumpFrom, E);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* There are no more instructions jumping to this label now */
|
||||||
|
CollDeleteAll (&L->JumpFrom);
|
||||||
|
|
||||||
/* Remove the label completely. */
|
/* Remove the label completely. */
|
||||||
FreeCodeLabel (L);
|
DelCodeLabel (S, L);
|
||||||
CollDelete (&E->Labels, J);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The reference label is the only remaining label. Check if there
|
/* The reference label is the only remaining label. Check if there
|
||||||
@@ -654,9 +720,7 @@ void MergeCodeLabels (CodeSeg* S)
|
|||||||
*/
|
*/
|
||||||
if (CollCount (&RefLab->JumpFrom) == 0) {
|
if (CollCount (&RefLab->JumpFrom) == 0) {
|
||||||
/* Delete the label */
|
/* Delete the label */
|
||||||
FreeCodeLabel (RefLab);
|
DelCodeLabel (S, RefLab);
|
||||||
/* Remove it from the list */
|
|
||||||
CollDelete (&E->Labels, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -95,9 +95,18 @@ CodeSeg* PopCodeSeg (void);
|
|||||||
void AddCodeSegLine (CodeSeg* S, const char* Format, ...) attribute ((format(printf,2,3)));
|
void AddCodeSegLine (CodeSeg* S, const char* Format, ...) attribute ((format(printf,2,3)));
|
||||||
/* Add a line to the given code segment */
|
/* Add a line to the given code segment */
|
||||||
|
|
||||||
|
void DelCodeSegLine (CodeSeg* S, unsigned Index);
|
||||||
|
/* Delete an entry from the code segment. This includes deleting any associated
|
||||||
|
* labels, removing references to labels and even removing the referenced labels
|
||||||
|
* if the reference count drops to zero.
|
||||||
|
*/
|
||||||
|
|
||||||
void AddCodeLabel (CodeSeg* S, const char* Name);
|
void AddCodeLabel (CodeSeg* S, const char* Name);
|
||||||
/* Add a code label for the next instruction to follow */
|
/* Add a code label for the next instruction to follow */
|
||||||
|
|
||||||
|
void DelCodeLabel (CodeSeg* S, CodeLabel* L);
|
||||||
|
/* Remove references from this label and delete it. */
|
||||||
|
|
||||||
void AddCodeSegHint (CodeSeg* S, unsigned Hint);
|
void AddCodeSegHint (CodeSeg* S, unsigned Hint);
|
||||||
/* Add a hint for the preceeding instruction */
|
/* Add a hint for the preceeding instruction */
|
||||||
|
|
||||||
|
@@ -6,10 +6,10 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998-2000 Ullrich von Bassewitz */
|
/* (C) 1998-2001 Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Wacholderweg 14 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70597 Stuttgart */
|
||||||
/* EMail: uz@musoftware.de */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
@@ -47,6 +47,7 @@ unsigned char ANSI = 0; /* Strict ANSI flag */
|
|||||||
unsigned char WriteableStrings = 0; /* Literal strings are r/w */
|
unsigned char WriteableStrings = 0; /* Literal strings are r/w */
|
||||||
unsigned char NoWarn = 0; /* Suppress warnings */
|
unsigned char NoWarn = 0; /* Suppress warnings */
|
||||||
unsigned char Optimize = 0; /* Optimize flag */
|
unsigned char Optimize = 0; /* Optimize flag */
|
||||||
|
unsigned long OptDisable = 0; /* Optimizer passes to disable */
|
||||||
unsigned char FavourSize = 1; /* Favour size over speed */
|
unsigned char FavourSize = 1; /* Favour size over speed */
|
||||||
unsigned CodeSizeFactor = 100; /* Size factor for generated code */
|
unsigned CodeSizeFactor = 100; /* Size factor for generated code */
|
||||||
unsigned char InlineStdFuncs = 0; /* Inline some known functions */
|
unsigned char InlineStdFuncs = 0; /* Inline some known functions */
|
||||||
|
@@ -6,10 +6,10 @@
|
|||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* (C) 1998 Ullrich von Bassewitz */
|
/* (C) 1998-2001 Ullrich von Bassewitz */
|
||||||
/* Wacholderweg 14 */
|
/* Wacholderweg 14 */
|
||||||
/* D-70597 Stuttgart */
|
/* D-70597 Stuttgart */
|
||||||
/* EMail: uz@musoftware.de */
|
/* EMail: uz@cc65.org */
|
||||||
/* */
|
/* */
|
||||||
/* */
|
/* */
|
||||||
/* This software is provided 'as-is', without any expressed or implied */
|
/* This software is provided 'as-is', without any expressed or implied */
|
||||||
@@ -48,6 +48,7 @@ extern unsigned char ANSI; /* Strict ANSI flag */
|
|||||||
extern unsigned char WriteableStrings; /* Literal strings are r/w */
|
extern unsigned char WriteableStrings; /* Literal strings are r/w */
|
||||||
extern unsigned char NoWarn; /* Suppress warnings */
|
extern unsigned char NoWarn; /* Suppress warnings */
|
||||||
extern unsigned char Optimize; /* Optimize flag */
|
extern unsigned char Optimize; /* Optimize flag */
|
||||||
|
extern unsigned long OptDisable; /* Optimizer passes to disable */
|
||||||
extern unsigned char FavourSize; /* Favour size over speed */
|
extern unsigned char FavourSize; /* Favour size over speed */
|
||||||
extern unsigned CodeSizeFactor; /* Size factor for generated code */
|
extern unsigned CodeSizeFactor; /* Size factor for generated code */
|
||||||
extern unsigned char InlineStdFuncs; /* Inline some known functions */
|
extern unsigned char InlineStdFuncs; /* Inline some known functions */
|
||||||
|
@@ -567,11 +567,9 @@ int main (int argc, char* argv[])
|
|||||||
P = Arg + 2;
|
P = Arg + 2;
|
||||||
while (*P) {
|
while (*P) {
|
||||||
switch (*P++) {
|
switch (*P++) {
|
||||||
#if 0
|
|
||||||
case 'f':
|
case 'f':
|
||||||
sscanf (P, "%lx", (long*) &OptDisable);
|
sscanf (P, "%lx", (long*) &OptDisable);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
case 'i':
|
case 'i':
|
||||||
FavourSize = 0;
|
FavourSize = 0;
|
||||||
CodeSizeFactor = 200;
|
CodeSizeFactor = 200;
|
||||||
|
@@ -213,4 +213,22 @@ const OPCDesc* GetOPCDesc (opc_t OPC)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned GetAMUseInfo (am_t AM)
|
||||||
|
/* Get usage info for the given addressing mode (addressing modes that use
|
||||||
|
* index registers return CI_USE... info for these registers).
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
/* Check the addressing mode. */
|
||||||
|
switch (AM) {
|
||||||
|
case AM_ACC: return CI_USE_A;
|
||||||
|
case AM_ZPX: return CI_USE_X;
|
||||||
|
case AM_ABSX: return CI_USE_X;
|
||||||
|
case AM_ABSY: return CI_USE_Y;
|
||||||
|
case AM_ZPX_IND: return CI_USE_X;
|
||||||
|
case AM_ZP_INDY: return CI_USE_Y;
|
||||||
|
default: return CI_USE_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@@ -165,6 +165,11 @@ unsigned GetInsnSize (opc_t OPC, am_t AM);
|
|||||||
const OPCDesc* GetOPCDesc (opc_t OPC);
|
const OPCDesc* GetOPCDesc (opc_t OPC);
|
||||||
/* Get an opcode description */
|
/* Get an opcode description */
|
||||||
|
|
||||||
|
unsigned GetAMUseInfo (am_t AM);
|
||||||
|
/* Get usage info for the given addressing mode (addressing modes that use
|
||||||
|
* index registers return CI_USE... info for these registers).
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* End of opcodes.h */
|
/* End of opcodes.h */
|
||||||
|
Reference in New Issue
Block a user