/*****************************************************************************/
/* */
-/* handler.c */
+/* handler.c */
/* */
-/* Opcode handler functions for the disassembler */
+/* Opcode handler functions for the disassembler */
/* */
/* */
/* */
-/* (C) 2000-2004 Ullrich von Bassewitz */
-/* Römerstrasse 52 */
-/* D-70794 Filderstadt */
-/* EMail: uz@cc65.org */
+/* (C) 2000-2011, Ullrich von Bassewitz */
+/* Roemerstrasse 52 */
+/* D-70794 Filderstadt */
+/* EMail: uz@cc65.org */
/* */
/* */
/* This software is provided 'as-is', without any expressed or implied */
#include <stdarg.h>
/* common */
+#include "xmalloc.h"
#include "xsprintf.h"
/* da65 */
/*****************************************************************************/
-/* Helper functions */
+/* Helper functions */
/*****************************************************************************/
xvsprintf (Buf, sizeof (Buf), Arg, ap);
va_end (ap);
Indent (ACol);
- Output (Buf);
+ Output ("%s", Buf);
/* Add the code stuff as comment */
LineComment (PC, D->Size);
static const char* GetAbsOverride (unsigned Flags, unsigned Addr)
/* If the instruction requires an abs override modifier, return the necessary
- * string, otherwise return the empty string.
- */
+** string, otherwise return the empty string.
+*/
{
if ((Flags & flAbsOverride) != 0 && Addr < 0x100) {
return "a:";
{
const char* Label = 0;
if (Flags & flUseLabel) {
- Label = GetLabel (Addr, PC);
+ Label = GetLabel (Addr, PC);
}
if (Label) {
- return Label;
+ return Label;
} else {
- static char Buf [32];
- if (Addr < 0x100) {
- xsprintf (Buf, sizeof (Buf), "$%02X", Addr);
- } else {
- xsprintf (Buf, sizeof (Buf), "$%04X", Addr);
- }
- return Buf;
+ static char Buf [32];
+ if (Addr < 0x100) {
+ xsprintf (Buf, sizeof (Buf), "$%02X", Addr);
+ } else {
+ xsprintf (Buf, sizeof (Buf), "$%04X", Addr);
+ }
+ return Buf;
}
}
{
/* Generate labels in pass #1, and only if we don't have a label already */
if (Pass == 1 && !HaveLabel (Addr) &&
- /* Check if we must create a label */
- ((Flags & flGenLabel) != 0 ||
- ((Flags & flUseLabel) != 0 && Addr >= CodeStart && Addr <= CodeEnd))) {
-
- /* As a special case, handle ranges with tables or similar. Within
- * such a range with a granularity > 1, do only generate dependent
- * labels for all addresses but the first one. Be sure to generate
- * a label for the start of the range, however.
- */
- attr_t Style = GetStyleAttr (Addr);
- unsigned Granularity = GetGranularity (Style);
-
- if (Granularity == 1) {
- /* Just add the label */
- AddIntLabel (Addr);
- } else {
+ /* Check if we must create a label */
+ ((Flags & flGenLabel) != 0 ||
+ ((Flags & flUseLabel) != 0 && Addr >= CodeStart && Addr <= CodeEnd))) {
+
+ /* As a special case, handle ranges with tables or similar. Within
+ ** such a range with a granularity > 1, do only generate dependent
+ ** labels for all addresses but the first one. Be sure to generate
+ ** a label for the start of the range, however.
+ */
+ attr_t Style = GetStyleAttr (Addr);
+ unsigned Granularity = GetGranularity (Style);
+
+ if (Granularity == 1) {
+ /* Just add the label */
+ AddIntLabel (Addr);
+ } else {
/* THIS CODE IS A MESS AND WILL FAIL ON SEVERAL CONDITIONS! ### */
- /* Search for the start of the range or the last non dependent
- * label in the range.
- */
- unsigned Offs;
- attr_t LabelAttr;
- unsigned LabelAddr = Addr;
- while (LabelAddr > CodeStart) {
-
- if (Style != GetStyleAttr (LabelAddr-1)) {
- /* End of range reached */
- break;
- }
- --LabelAddr;
- LabelAttr = GetLabelAttr (LabelAddr);
- if ((LabelAttr & (atIntLabel|atExtLabel)) != 0) {
- /* The address has an internal or external label */
- break;
- }
- }
-
- /* If the proposed label address doesn't have a label, define one */
- if ((GetLabelAttr (LabelAddr) & (atIntLabel|atExtLabel)) == 0) {
- AddIntLabel (LabelAddr);
- }
-
- /* Create the label */
- Offs = Addr - LabelAddr;
- if (Offs == 0) {
- AddIntLabel (Addr);
- } else {
- AddDepLabel (Addr, atIntLabel, GetLabelName (LabelAddr), Offs);
- }
- }
+ /* Search for the start of the range or the last non dependent
+ ** label in the range.
+ */
+ unsigned Offs;
+ attr_t LabelAttr;
+ unsigned LabelAddr = Addr;
+ while (LabelAddr > CodeStart) {
+
+ if (Style != GetStyleAttr (LabelAddr-1)) {
+ /* End of range reached */
+ break;
+ }
+ --LabelAddr;
+ LabelAttr = GetLabelAttr (LabelAddr);
+ if ((LabelAttr & (atIntLabel|atExtLabel)) != 0) {
+ /* The address has an internal or external label */
+ break;
+ }
+ }
+
+ /* If the proposed label address doesn't have a label, define one */
+ if ((GetLabelAttr (LabelAddr) & (atIntLabel|atExtLabel)) == 0) {
+ AddIntLabel (LabelAddr);
+ }
+
+ /* Create the label */
+ Offs = Addr - LabelAddr;
+ if (Offs == 0) {
+ AddIntLabel (Addr);
+ } else {
+ AddDepLabel (Addr, atIntLabel, GetLabelName (LabelAddr), Offs);
+ }
+ }
}
}
/*****************************************************************************/
-/* Code */
+/* Code */
/*****************************************************************************/
-void OH_Immidiate (const OpcDesc* D)
+void OH_Immediate (const OpcDesc* D)
{
OneLine (D, "#$%02X", GetCodeByte (PC+1));
}
void OH_BitBranch (const OpcDesc* D)
{
+ char* BranchLabel;
+
/* Get the operands */
unsigned char TestAddr = GetCodeByte (PC+1);
signed char BranchOffs = GetCodeByte (PC+2);
unsigned BranchAddr = (((int) PC+3) + BranchOffs) & 0xFFFF;
/* Generate labels in pass 1. The bit branch codes are special in that
- * they don't really match the remainder of the 6502 instruction set (they
- * are a Rockwell addon), so we must pass additional flags as direct
- * value to the second GenerateLabel call.
- */
+ ** they don't really match the remainder of the 6502 instruction set (they
+ ** are a Rockwell addon), so we must pass additional flags as direct
+ ** value to the second GenerateLabel call.
+ */
GenerateLabel (D->Flags, TestAddr);
GenerateLabel (flLabel, BranchAddr);
+ /* Make a copy of an operand, so that
+ ** the other operand can't overwrite it.
+ ** [GetAddrArg() uses a statically-stored buffer.]
+ */
+ BranchLabel = xstrdup (GetAddrArg (flLabel, BranchAddr));
+
+ /* Output the line */
+ OneLine (D, "%s,%s", GetAddrArg (D->Flags, TestAddr), BranchLabel);
+
+ xfree (BranchLabel);
+}
+
+
+
+void OH_ImmediateDirect (const OpcDesc* D)
+{
+ /* Get the operand */
+ unsigned Addr = GetCodeByte (PC+2);
+
+ /* Generate a label in pass 1 */
+ GenerateLabel (D->Flags, Addr);
+
+ /* Output the line */
+ OneLine (D, "#$%02X,%s", GetCodeByte (PC+1), GetAddrArg (D->Flags, Addr));
+}
+
+
+
+void OH_ImmediateDirectX (const OpcDesc* D)
+{
+ /* Get the operand */
+ unsigned Addr = GetCodeByte (PC+2);
+
+ /* Generate a label in pass 1 */
+ GenerateLabel (D->Flags, Addr);
+
/* Output the line */
- OneLine (D, "%s,%s", GetAddrArg (D->Flags, TestAddr), GetAddrArg (flLabel, BranchAddr));
+ OneLine (D, "#$%02X,%s,x", GetCodeByte (PC+1), GetAddrArg (D->Flags, Addr));
+}
+
+
+
+void OH_ImmediateAbsolute (const OpcDesc* D)
+{
+ /* Get the operand */
+ unsigned Addr = GetCodeWord (PC+2);
+
+ /* Generate a label in pass 1 */
+ GenerateLabel (D->Flags, Addr);
+
+ /* Output the line */
+ OneLine (D, "#$%02X,%s%s", GetCodeByte (PC+1), GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
+}
+
+
+
+void OH_ImmediateAbsoluteX (const OpcDesc* D)
+{
+ /* Get the operand */
+ unsigned Addr = GetCodeWord (PC+2);
+
+ /* Generate a label in pass 1 */
+ GenerateLabel (D->Flags, Addr);
+
+ /* Output the line */
+ OneLine (D, "#$%02X,%s%s,x", GetCodeByte (PC+1), GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
}
-void OH_BlockMove (const OpcDesc* D attribute ((unused)))
+void OH_BlockMove (const OpcDesc* D)
{
- Error ("Not implemented");
+ char* DstLabel;
+
+ /* Get source operand */
+ unsigned Src = GetCodeWord (PC+1);
+ /* Get destination operand */
+ unsigned Dst = GetCodeWord (PC+3);
+
+ /* Generate a label in pass 1 */
+ GenerateLabel (D->Flags, Src);
+ GenerateLabel (D->Flags, Dst);
+
+ /* Make a copy of an operand, so that
+ ** the other operand can't overwrite it.
+ ** [GetAddrArg() uses a statically-stored buffer.]
+ */
+ DstLabel = xstrdup (GetAddrArg (D->Flags, Dst));
+
+ /* Output the line */
+ OneLine (D, "%s%s,%s%s,$%04X",
+ GetAbsOverride (D->Flags, Src), GetAddrArg (D->Flags, Src),
+ GetAbsOverride (D->Flags, Dst), DstLabel,
+ GetCodeWord (PC+5));
+
+ xfree (DstLabel);
}
+void OH_DirectImmediate (const OpcDesc* D)
+{
+ /* Get the operand */
+ unsigned Addr = GetCodeByte (PC+1);
+
+ /* Generate a label in pass 1 */
+ GenerateLabel (D->Flags, Addr);
+
+ /* Output the line */
+ OneLine (D, "%s, #$%02X", GetAddrArg (D->Flags, Addr), GetCodeByte (PC+2));
+}
+
+
+
+void OH_ZeroPageBit (const OpcDesc* D)
+{
+ unsigned Bit = GetCodeByte (PC) >> 5;
+ unsigned Addr = GetCodeByte (PC+1);
+
+ /* Generate a label in pass 1 */
+ GenerateLabel (D->Flags, Addr);
+
+ /* Output the line */
+ OneLine (D, "%01X,%s", Bit, GetAddrArg (D->Flags, Addr));
+}
+
+
+
+void OH_AccumulatorBit (const OpcDesc* D)
+{
+ unsigned Bit = GetCodeByte (PC) >> 5;
+
+ /* Output the line */
+ OneLine (D, "%01X,a", Bit);
+}
+
+
+
+void OH_AccumulatorBitBranch (const OpcDesc* D)
+{
+ unsigned Bit = GetCodeByte (PC) >> 5;
+ signed char BranchOffs = GetCodeByte (PC+1);
+
+ /* Calculate the target address for the branch */
+ unsigned BranchAddr = (((int) PC+3) + BranchOffs) & 0xFFFF;
+
+ /* Generate labels in pass 1 */
+ GenerateLabel (flLabel, BranchAddr);
+
+ /* Output the line */
+ OneLine (D, "%01X,a,%s", Bit, GetAddrArg (flLabel, BranchAddr));
+}
+
+
+
+void OH_JmpDirectIndirect (const OpcDesc* D)
+{
+ OH_DirectIndirect (D);
+ if (NewlineAfterJMP) {
+ LineFeed ();
+ }
+ SeparatorLine ();
+}
+
+
+
+void OH_SpecialPage (const OpcDesc* D)
+{
+ /* Get the operand */
+ unsigned Addr = 0xFF00 + GetCodeByte (PC+1);
+
+ /* Generate a label in pass 1 */
+ GenerateLabel (D->Flags, Addr);
+
+ /* OneLine (D, "$FF%02X", (CodeByte (PC+1)); */
+ OneLine (D, "%s", GetAddrArg (D->Flags, Addr));
+}
+
+
+
void OH_Rts (const OpcDesc* D)
{
OH_Implicit (D);
+ if (NewlineAfterRTS) {
+ LineFeed ();
+ }
SeparatorLine();
}
void OH_JmpAbsolute (const OpcDesc* D)
{
OH_Absolute (D);
+ if (NewlineAfterJMP) {
+ LineFeed ();
+ }
SeparatorLine ();
}
void OH_JmpAbsoluteIndirect (const OpcDesc* D)
{
OH_AbsoluteIndirect (D);
+ if (NewlineAfterJMP) {
+ LineFeed ();
+ }
SeparatorLine ();
}
+void OH_JmpAbsoluteXIndirect (const OpcDesc* D)
+{
+ OH_AbsoluteXIndirect (D);
+ if (NewlineAfterJMP) {
+ LineFeed ();
+ }
+ SeparatorLine ();
+}