2001-04-30 20:00:13 +00:00
|
|
|
/*****************************************************************************/
|
|
|
|
/* */
|
|
|
|
/* 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 */
|
2001-05-01 09:21:32 +00:00
|
|
|
#include "check.h"
|
2001-04-30 20:00:13 +00:00
|
|
|
#include "xmalloc.h"
|
|
|
|
|
2001-05-01 09:21:32 +00:00
|
|
|
/* cc65 */
|
|
|
|
#include "codeinfo.h"
|
2001-05-05 11:46:02 +00:00
|
|
|
#include "error.h"
|
|
|
|
#include "global.h"
|
|
|
|
#include "codelab.h"
|
2001-04-30 20:00:13 +00:00
|
|
|
#include "opcodes.h"
|
|
|
|
#include "codeent.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* Data */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
/* Code */
|
|
|
|
/*****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
2001-05-05 11:31:05 +00:00
|
|
|
CodeEntry* NewCodeEntry (const OPCDesc* D, am_t AM, const char* Arg, CodeLabel* JumpTo)
|
2001-04-30 20:00:13 +00:00
|
|
|
/* Create a new code entry, initialize and return it */
|
|
|
|
{
|
|
|
|
/* Allocate memory */
|
|
|
|
CodeEntry* E = xmalloc (sizeof (CodeEntry));
|
|
|
|
|
|
|
|
/* Initialize the fields */
|
2001-05-05 11:31:05 +00:00
|
|
|
E->OPC = D->OPC;
|
|
|
|
E->AM = AM;
|
|
|
|
E->Size = GetInsnSize (E->OPC, E->AM);
|
2001-04-30 20:00:13 +00:00
|
|
|
E->Hints = 0;
|
2001-05-05 11:31:05 +00:00
|
|
|
E->Arg = (Arg && Arg[0] != '\0')? xstrdup (Arg) : 0;
|
|
|
|
E->Num = 0;
|
2001-04-30 20:00:13 +00:00
|
|
|
E->Flags = 0;
|
2001-05-05 21:42:58 +00:00
|
|
|
E->Info = D->Info;
|
2001-05-05 16:12:47 +00:00
|
|
|
E->Use = D->Use;
|
|
|
|
E->Chg = D->Chg;
|
2001-05-05 11:31:05 +00:00
|
|
|
if (E->OPC == OPC_JSR && E->Arg) {
|
|
|
|
/* A subroutine call */
|
2001-05-05 16:12:47 +00:00
|
|
|
GetFuncInfo (E->Arg, &E->Use, &E->Chg);
|
2001-05-05 11:31:05 +00:00
|
|
|
} else {
|
|
|
|
/* Some other instruction */
|
2001-05-05 16:12:47 +00:00
|
|
|
E->Use |= GetAMUseInfo (AM);
|
2001-05-05 11:31:05 +00:00
|
|
|
}
|
2001-05-01 09:21:32 +00:00
|
|
|
E->JumpTo = JumpTo;
|
2001-04-30 20:00:13 +00:00
|
|
|
InitCollection (&E->Labels);
|
|
|
|
|
2001-05-01 09:21:32 +00:00
|
|
|
/* If we have a label given, add this entry to the label */
|
|
|
|
if (JumpTo) {
|
|
|
|
CollAppend (&JumpTo->JumpFrom, E);
|
|
|
|
}
|
|
|
|
|
2001-04-30 20:00:13 +00:00
|
|
|
/* Return the initialized struct */
|
|
|
|
return E;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void FreeCodeEntry (CodeEntry* E)
|
|
|
|
/* Free the given code entry */
|
|
|
|
{
|
2001-05-04 16:41:23 +00:00
|
|
|
/* Free the string argument if we have one */
|
|
|
|
xfree (E->Arg);
|
2001-04-30 20:00:13 +00:00
|
|
|
|
|
|
|
/* Cleanup the collection */
|
|
|
|
DoneCollection (&E->Labels);
|
|
|
|
|
|
|
|
/* Free the entry */
|
|
|
|
xfree (E);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2001-05-04 16:41:23 +00:00
|
|
|
int CodeEntryHasLabel (const CodeEntry* E)
|
|
|
|
/* Check if the given code entry has labels attached */
|
|
|
|
{
|
|
|
|
return (CollCount (&E->Labels) > 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2001-05-05 21:42:58 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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. */
|
|
|
|
{
|
|
|
|
/* Delete the label from the owner */
|
|
|
|
CollDeleteItem (&L->Owner->Labels, L);
|
|
|
|
|
|
|
|
/* Set the new owner */
|
|
|
|
CollAppend (&E->Labels, L);
|
|
|
|
L->Owner = E;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2001-05-05 13:51:42 +00:00
|
|
|
void OutputCodeEntry (const CodeEntry* E, FILE* F)
|
2001-04-30 20:00:13 +00:00
|
|
|
/* Output the code entry to a file */
|
|
|
|
{
|
|
|
|
const OPCDesc* D;
|
2001-05-04 16:41:23 +00:00
|
|
|
unsigned Chars;
|
2001-04-30 20:00:13 +00:00
|
|
|
|
|
|
|
/* If we have a label, print that */
|
|
|
|
unsigned LabelCount = CollCount (&E->Labels);
|
|
|
|
unsigned I;
|
|
|
|
for (I = 0; I < LabelCount; ++I) {
|
2001-05-05 13:51:42 +00:00
|
|
|
OutputCodeLabel (CollConstAt (&E->Labels, I), F);
|
2001-04-30 20:00:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Get the opcode description */
|
|
|
|
D = GetOPCDesc (E->OPC);
|
|
|
|
|
|
|
|
/* Print the mnemonic */
|
2001-05-04 16:41:23 +00:00
|
|
|
Chars = fprintf (F, "\t%s", D->Mnemo);
|
2001-04-30 20:00:13 +00:00
|
|
|
|
|
|
|
/* Print the operand */
|
|
|
|
switch (E->AM) {
|
|
|
|
|
2001-05-04 16:41:23 +00:00
|
|
|
case AM_IMP:
|
|
|
|
/* implicit */
|
|
|
|
break;
|
2001-05-01 09:21:32 +00:00
|
|
|
|
2001-05-04 16:41:23 +00:00
|
|
|
case AM_ACC:
|
|
|
|
/* accumulator */
|
|
|
|
Chars += fprintf (F, "%*sa", 9-Chars, "");
|
|
|
|
break;
|
2001-04-30 20:00:13 +00:00
|
|
|
|
2001-05-04 16:41:23 +00:00
|
|
|
case AM_IMM:
|
|
|
|
/* immidiate */
|
|
|
|
Chars += fprintf (F, "%*s#%s", 9-Chars, "", E->Arg);
|
|
|
|
break;
|
2001-04-30 20:00:13 +00:00
|
|
|
|
2001-05-04 16:41:23 +00:00
|
|
|
case AM_ZP:
|
|
|
|
case AM_ABS:
|
2001-05-01 09:21:32 +00:00
|
|
|
/* zeropage and absolute */
|
2001-05-04 16:41:23 +00:00
|
|
|
Chars += fprintf (F, "%*s%s", 9-Chars, "", E->Arg);
|
2001-04-30 20:00:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AM_ZPX:
|
|
|
|
case AM_ABSX:
|
|
|
|
/* zeropage,X and absolute,X */
|
2001-05-04 16:41:23 +00:00
|
|
|
Chars += fprintf (F, "%*s%s,x", 9-Chars, "", E->Arg);
|
2001-04-30 20:00:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AM_ABSY:
|
|
|
|
/* absolute,Y */
|
2001-05-04 16:41:23 +00:00
|
|
|
Chars += fprintf (F, "%*s%s,y", 9-Chars, "", E->Arg);
|
2001-04-30 20:00:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AM_ZPX_IND:
|
|
|
|
/* (zeropage,x) */
|
2001-05-04 16:41:23 +00:00
|
|
|
Chars += fprintf (F, "%*s(%s,x)", 9-Chars, "", E->Arg);
|
2001-04-30 20:00:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AM_ZP_INDY:
|
|
|
|
/* (zeropage),y */
|
2001-05-04 16:41:23 +00:00
|
|
|
Chars += fprintf (F, "%*s(%s),y", 9-Chars, "", E->Arg);
|
2001-04-30 20:00:13 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AM_ZP_IND:
|
|
|
|
/* (zeropage) */
|
2001-05-04 16:41:23 +00:00
|
|
|
Chars += fprintf (F, "%*s(%s)", 9-Chars, "", E->Arg);
|
2001-04-30 20:00:13 +00:00
|
|
|
break;
|
|
|
|
|
2001-05-01 09:21:32 +00:00
|
|
|
case AM_BRA:
|
|
|
|
/* branch */
|
|
|
|
CHECK (E->JumpTo != 0);
|
2001-05-04 16:41:23 +00:00
|
|
|
Chars += fprintf (F, "%*s%s", 9-Chars, "", E->JumpTo->Name);
|
2001-05-01 09:21:32 +00:00
|
|
|
break;
|
|
|
|
|
2001-04-30 20:00:13 +00:00
|
|
|
default:
|
|
|
|
Internal ("Invalid addressing mode");
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2001-05-04 16:41:23 +00:00
|
|
|
/* 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, "",
|
2001-05-05 16:12:47 +00:00
|
|
|
(E->Use & REG_A)? 'A' : '_',
|
|
|
|
(E->Use & REG_X)? 'X' : '_',
|
|
|
|
(E->Use & REG_Y)? 'Y' : '_',
|
|
|
|
(E->Chg & REG_A)? 'A' : '_',
|
|
|
|
(E->Chg & REG_X)? 'X' : '_',
|
|
|
|
(E->Chg & REG_Y)? 'Y' : '_');
|
2001-05-04 16:41:23 +00:00
|
|
|
// }
|
|
|
|
|
2001-04-30 20:00:13 +00:00
|
|
|
/* Terminate the line */
|
|
|
|
fprintf (F, "\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|