Merge pull request #1871 from clbr/da816

da65 support for 65816
This commit is contained in:
Bob Andrews 2022-12-30 15:34:40 +01:00 committed by GitHub
commit cce119a9e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 834 additions and 85 deletions

View File

@ -115,14 +115,14 @@ Here is a description of all the command line options:
<item>6502dtv
<item>65sc02
<item>65c02
<item>65816
<item>huc6280
<item>4510
</itemize>
6502x is for the NMOS 6502 with unofficial opcodes. 6502dtv is for the
emulated CPU of the C64DTV device. huc6280 is the CPU of the PC engine.
4510 is the CPU of the Commodore C65. Support for the 65816 currently
is not available.
4510 is the CPU of the Commodore C65. 65816 is the CPU of the SNES.
<label id="option--formfeeds">
@ -263,8 +263,9 @@ can produce output that can not be re-assembled, when one or more of those
branches point outside of the disassembled memory. This can happen when text
or binary data is processed.
While there is some code for the 65816 in the sources, it is currently
unsupported.
The 65816 support requires annotating ranges with the M and X flag states.
This can be recorded with an emulator that supports Code and Data Logging,
for example. Disassemble one bank at a time.
<sect1>Attribute map<p>
@ -521,6 +522,11 @@ following attributes are recognized:
</descrip>
<tag><tt>ADDRMODE</tt></tag>
When disassembling 65816 code, this specifies the M and X flag states
for this range. It's a string argument of the form "mx", capital letters
mean the flag is enabled.
</descrip>
@ -693,6 +699,20 @@ directives explained above:
<sect>Helper scripts<p>
<tt>util/parse-bsnes-log.awk</tt> is a supplied script for 65816 disassembly,
to parse bsnes-plus Code-Data log files and output the RANGE sections
for your info file. For typical usage, you'd check the S-CPU log and trace
log mask boxes in the bsnes-plus debugger, play through the game, then grep
for the bank you're disassembling, and pass that to this script.
<tscreen><verb>
grep ^83 my-game-log | parse-bsnes-log.awk
</verb></tscreen>
<sect>Copyright<p>
da65 (and all cc65 binutils) is (C) Copyright 1998-2011, Ullrich von

View File

@ -34,6 +34,7 @@
/* da65 */
#include "cpu.h"
#include "error.h"
#include "attrtab.h"
@ -48,6 +49,12 @@
/* Attribute table */
static unsigned short AttrTab[0x10000];
/* 65816 attribute table */
#define MAX_LONG_ATTRS 256
static unsigned short LongAttrVal[MAX_LONG_ATTRS];
static unsigned LongAttrAddr[MAX_LONG_ATTRS];
static unsigned LongAttrsUsed;
/*****************************************************************************/
@ -59,12 +66,19 @@ static unsigned short AttrTab[0x10000];
void AddrCheck (unsigned Addr)
/* Check if the given address has a valid range */
{
if (Addr >= 0x10000) {
if (Addr >= 0x10000 && CPU != CPU_65816) {
Error ("Address out of range: %08X", Addr);
}
}
unsigned char IsLongAddr (unsigned Addr)
/* Is it 24-bit? */
{
return Addr >= 0x10000 && CPU == CPU_65816;
}
attr_t GetAttr (unsigned Addr)
/* Return the attribute for the given address */
@ -72,6 +86,17 @@ attr_t GetAttr (unsigned Addr)
/* Check the given address */
AddrCheck (Addr);
if (IsLongAddr (Addr)) {
unsigned i;
for (i = 0; i < LongAttrsUsed; i++) {
if (LongAttrAddr[i] == Addr) {
return LongAttrVal[i];
}
}
return 0;
}
/* Return the attribute */
return AttrTab[Addr];
}
@ -148,6 +173,33 @@ void MarkAddr (unsigned Addr, attr_t Attr)
/* Check the given address */
AddrCheck (Addr);
if (IsLongAddr (Addr)) {
unsigned i;
for (i = 0; i < LongAttrsUsed; i++) {
if (LongAttrAddr[i] == Addr) {
/* We must not have more than one style bit */
if (Attr & atStyleMask) {
if (LongAttrVal[i] & atStyleMask) {
Error ("Duplicate style for long address %06X", Addr);
}
}
LongAttrVal[i] |= Attr;
return;
}
}
if (LongAttrsUsed >= MAX_LONG_ATTRS) {
Error ("Too many long addresses");
}
LongAttrVal[LongAttrsUsed] |= Attr;
LongAttrAddr[LongAttrsUsed] = Addr;
LongAttrsUsed++;
return;
}
/* We must not have more than one style bit */
if (Attr & atStyleMask) {
if (AttrTab[Addr] & atStyleMask) {
@ -168,7 +220,7 @@ attr_t GetStyleAttr (unsigned Addr)
AddrCheck (Addr);
/* Return the attribute */
return (AttrTab[Addr] & atStyleMask);
return (GetAttr (Addr) & atStyleMask);
}
@ -180,5 +232,5 @@ attr_t GetLabelAttr (unsigned Addr)
AddrCheck (Addr);
/* Return the attribute */
return (AttrTab[Addr] & atLabelMask);
return (GetAttr (Addr) & atLabelMask);
}

View File

@ -66,15 +66,22 @@ typedef enum attr_t {
atDepLabel = 0x0040, /* Dependent label */
atUnnamedLabel = 0x0080, /* Unnamed label */
atLabelDefined = 0x0100, /* True if we defined the label */
atStyleMask = 0x000F, /* Output style */
atLabelMask = 0x00F0, /* Label information */
/* Segment */
atSegment = 0x0100, /* Code is in a segment */
atSegmentEnd = 0x0200, /* Segment end */
atSegmentStart = 0x0400, /* Segment start */
/* 65816 addressing mode */
atMem8 = 0x1000, /* M flag enabled, 8-bit */
atMem16 = 0x2000, /* M flag disabled, 16-bit */
atIdx8 = 0x4000, /* X flag enabled, 8-bit */
atIdx16 = 0x8000, /* X flag disabled, 16-bit */
atStyleMask = 0x000F, /* Output style */
atLabelMask = 0x00F0, /* Label information */
atSegmentMask = 0x0F00, /* Segment information */
at65816Mask = 0xF000, /* 65816 information */
} attr_t;
@ -88,6 +95,9 @@ typedef enum attr_t {
void AddrCheck (unsigned Addr);
/* Check if the given address has a valid range */
unsigned char IsLongAddr (unsigned Addr);
/* Check if the given address is 24-bit */
attr_t GetAttr (unsigned Addr);
/* Return the attribute for the given address */

View File

@ -194,6 +194,17 @@ unsigned long GetCodeDWord (unsigned Addr)
unsigned GetCodeLongAddr (unsigned Addr)
/* Get a word from the given address */
{
unsigned Lo = GetCodeByte (Addr);
unsigned Mid = GetCodeByte (Addr+1);
unsigned Hi = GetCodeByte (Addr+2);
return Lo | (Mid << 8) | (Hi << 16);
}
unsigned GetRemainingBytes (void)
/* Return the number of remaining code bytes */
{

View File

@ -72,6 +72,9 @@ unsigned GetCodeWord (unsigned Addr);
unsigned long GetCodeDWord (unsigned Addr);
/* Get a dword from the given address */
unsigned GetCodeLongAddr (unsigned Addr);
/* Get a 24-bit address from the given address */
unsigned GetRemainingBytes (void);
/* Return the number of remaining code bytes */

View File

@ -52,6 +52,11 @@
/* Comment table */
static const char* CommentTab[0x10000];
#define MAX_LONG_COMMENTS 256
static const char* LongCommentVal[MAX_LONG_COMMENTS];
static unsigned LongCommentAddr[MAX_LONG_COMMENTS];
static unsigned LongCommentsUsed;
/*****************************************************************************/
@ -60,17 +65,43 @@ static const char* CommentTab[0x10000];
static unsigned FindLongIndex (unsigned Addr)
{
unsigned i;
for (i = 0; i < LongCommentsUsed; i++) {
if (LongCommentAddr[i] == Addr) {
return i;
}
}
return -1;
}
void SetComment (unsigned Addr, const char* Comment)
/* Set a comment for the given address */
{
/* Check the given address */
AddrCheck (Addr);
/* If we do already have a comment, warn and ignore the new one */
if (CommentTab[Addr]) {
Warning ("Duplicate comment for address $%04X", Addr);
if (IsLongAddr (Addr)) {
if (FindLongIndex (Addr)) {
Warning ("Duplicate comment for address $%06X", Addr);
} else {
if (LongCommentsUsed >= MAX_LONG_COMMENTS) {
Error("Too many long-address comments");
}
LongCommentVal[LongCommentsUsed] = xstrdup (Comment);
LongCommentAddr[LongCommentsUsed] = Addr;
LongCommentsUsed++;
}
} else {
CommentTab[Addr] = xstrdup (Comment);
/* If we do already have a comment, warn and ignore the new one */
if (CommentTab[Addr]) {
Warning ("Duplicate comment for address $%04X", Addr);
} else {
CommentTab[Addr] = xstrdup (Comment);
}
}
}
@ -82,6 +113,14 @@ const char* GetComment (unsigned Addr)
/* Check the given address */
AddrCheck (Addr);
if (IsLongAddr (Addr)) {
const unsigned i = FindLongIndex (Addr);
if (i < LongCommentsUsed) {
return LongCommentVal[i];
}
return NULL;
}
/* Return the label if any */
return CommentTab[Addr];
}

View File

@ -99,7 +99,9 @@ static const char* GetAbsOverride (unsigned Flags, unsigned Addr)
** string, otherwise return the empty string.
*/
{
if ((Flags & flAbsOverride) != 0 && Addr < 0x100) {
if ((Flags & flFarOverride) != 0 && Addr < 0x10000) {
return "f:";
} else if ((Flags & flAbsOverride) != 0 && Addr < 0x100) {
return "a:";
} else {
return "";
@ -121,8 +123,10 @@ static const char* GetAddrArg (unsigned Flags, unsigned Addr)
static char Buf [32];
if (Addr < 0x100) {
xsprintf (Buf, sizeof (Buf), "$%02X", Addr);
} else {
} else if (Addr < 0x10000) {
xsprintf (Buf, sizeof (Buf), "$%04X", Addr);
} else {
xsprintf (Buf, sizeof (Buf), "$%06X", Addr);
}
return Buf;
}
@ -229,6 +233,28 @@ void OH_Immediate (const OpcDesc* D)
void OH_Immediate65816M (const OpcDesc* D)
{
if (GetAttr (PC) & atMem16) {
OneLine (D, "#$%04X", GetCodeWord (PC+1));
} else {
OneLine (D, "#$%02X", GetCodeByte (PC+1));
}
}
void OH_Immediate65816X (const OpcDesc* D)
{
if (GetAttr (PC) & atIdx16) {
OneLine (D, "#$%04X", GetCodeWord (PC+1));
} else {
OneLine (D, "#$%02X", GetCodeByte (PC+1));
}
}
void OH_ImmediateWord (const OpcDesc* D)
{
OneLine (D, "#$%04X", GetCodeWord (PC+1));
@ -322,14 +348,28 @@ void OH_AbsoluteY (const OpcDesc* D)
void OH_AbsoluteLong (const OpcDesc* D attribute ((unused)))
{
Error ("Not implemented");
/* Get the operand */
unsigned Addr = GetCodeLongAddr (PC+1);
/* Generate a label in pass 1 */
GenerateLabel (D->Flags, Addr);
/* Output the line */
OneLine (D, "%s%s", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
}
void OH_AbsoluteLongX (const OpcDesc* D attribute ((unused)))
{
Error ("Not implemented");
/* Get the operand */
unsigned Addr = GetCodeLongAddr (PC+1);
/* Generate a label in pass 1 */
GenerateLabel (D->Flags, Addr);
/* Output the line */
OneLine (D, "%s%s,x", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
}
@ -358,7 +398,17 @@ void OH_Relative (const OpcDesc* D)
void OH_RelativeLong (const OpcDesc* D attribute ((unused)))
{
Error ("Not implemented");
/* Get the operand */
signed short Offs = GetCodeWord (PC+1);
/* Calculate the target address */
unsigned Addr = (((int) PC+3) + Offs) & 0xFFFF;
/* Generate a label in pass 1 */
GenerateLabel (D->Flags, Addr);
/* Output the line */
OneLine (D, "%s", GetAddrArg (D->Flags, Addr));
}
@ -541,14 +591,15 @@ void OH_ImmediateAbsoluteX (const OpcDesc* D)
void OH_StackRelative (const OpcDesc* D attribute ((unused)))
{
Error ("Not implemented");
/* Output the line */
OneLine (D, "$%02X,s", GetCodeByte (PC+1));
}
void OH_DirectIndirectLongX (const OpcDesc* D attribute ((unused)))
{
Error ("Not implemented");
Error ("Not implemented %s", __FUNCTION__);
}
@ -571,14 +622,28 @@ void OH_StackRelativeIndirectY4510 (const OpcDesc* D attribute ((unused)))
void OH_DirectIndirectLong (const OpcDesc* D attribute ((unused)))
{
Error ("Not implemented");
/* Get the operand */
unsigned Addr = GetCodeByte (PC+1);
/* Generate a label in pass 1 */
GenerateLabel (D->Flags, Addr);
/* Output the line */
OneLine (D, "[%s]", GetAddrArg (D->Flags, Addr));
}
void OH_DirectIndirectLongY (const OpcDesc* D attribute ((unused)))
{
Error ("Not implemented");
/* Get the operand */
unsigned Addr = GetCodeByte (PC+1);
/* Generate a label in pass 1 */
GenerateLabel (D->Flags, Addr);
/* Output the line */
OneLine (D, "[%s],y", GetAddrArg (D->Flags, Addr));
}
@ -613,6 +678,19 @@ void OH_BlockMove (const OpcDesc* D)
void OH_BlockMove65816 (const OpcDesc* D)
{
/* Get source operand */
unsigned Src = GetCodeByte (PC+2);
/* Get destination operand */
unsigned Dst = GetCodeByte (PC+1);
/* Output the line */
OneLine (D, "#$%02X, #$%02X", Src, Dst);
}
void OH_AbsoluteXIndirect (const OpcDesc* D attribute ((unused)))
{
/* Get the operand */

View File

@ -57,6 +57,8 @@ void OH_Illegal (const OpcDesc* D attribute ((unused)));
void OH_Accumulator (const OpcDesc*);
void OH_Implicit (const OpcDesc*);
void OH_Immediate (const OpcDesc*);
void OH_Immediate65816M (const OpcDesc*);
void OH_Immediate65816X (const OpcDesc*);
void OH_ImmediateWord (const OpcDesc*);
void OH_Direct (const OpcDesc*);
void OH_DirectX (const OpcDesc*);
@ -89,6 +91,7 @@ void OH_StackRelativeIndirectY4510 (const OpcDesc*);
void OH_DirectIndirectLong (const OpcDesc*);
void OH_DirectIndirectLongY (const OpcDesc*);
void OH_BlockMove (const OpcDesc*);
void OH_BlockMove65816 (const OpcDesc*);
void OH_AbsoluteXIndirect (const OpcDesc*);
/* Mitsubishi 740 */

View File

@ -35,6 +35,7 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#if defined(_MSC_VER)
/* Microsoft compiler */
@ -521,11 +522,12 @@ static void RangeSection (void)
/* Parse a range section */
{
static const IdentTok RangeDefs[] = {
{ "COMMENT", INFOTOK_COMMENT },
{ "END", INFOTOK_END },
{ "NAME", INFOTOK_NAME },
{ "START", INFOTOK_START },
{ "TYPE", INFOTOK_TYPE },
{ "COMMENT", INFOTOK_COMMENT },
{ "END", INFOTOK_END },
{ "NAME", INFOTOK_NAME },
{ "START", INFOTOK_START },
{ "TYPE", INFOTOK_TYPE },
{ "ADDRMODE", INFOTOK_ADDRMODE },
};
static const IdentTok TypeDefs[] = {
@ -543,12 +545,13 @@ static void RangeSection (void)
/* Which values did we get? */
enum {
tNone = 0x00,
tStart = 0x01,
tEnd = 0x02,
tType = 0x04,
tName = 0x08,
tComment= 0x10,
tNone = 0x00,
tStart = 0x01,
tEnd = 0x02,
tType = 0x04,
tName = 0x08,
tComment = 0x10,
tAddrMode = 0x20,
tNeeded = (tStart | tEnd | tType)
};
unsigned Attributes = tNone;
@ -557,6 +560,7 @@ static void RangeSection (void)
unsigned Start = 0;
unsigned End = 0;
unsigned char Type = 0;
unsigned AddrMode = 0;
char* Name = 0;
char* Comment = 0;
unsigned MemberSize = 0;
@ -647,6 +651,37 @@ static void RangeSection (void)
InfoNextTok ();
break;
case INFOTOK_ADDRMODE:
AddAttr ("ADDRMODE", &Attributes, tAddrMode);
InfoNextTok ();
InfoAssureStr ();
if (InfoSVal[0] == '\0') {
InfoError ("AddrMode may not be empty");
}
if (InfoSVal[1] == '\0') {
InfoError ("AddrMode must be two characters long");
}
if (tolower(InfoSVal[0]) == 'm') {
if (InfoSVal[0] == 'm') {
AddrMode = atMem16;
} else {
AddrMode = atMem8;
}
} else {
InfoError ("AddrMode syntax: mx");
}
if (tolower(InfoSVal[1]) == 'x') {
if (InfoSVal[1] == 'x') {
AddrMode |= atIdx16;
} else {
AddrMode |= atIdx8;
}
} else {
InfoError ("AddrMode syntax: mx");
}
InfoNextTok ();
break;
default:
Internal ("Unexpected token: %u", InfoTok);
}
@ -661,6 +696,15 @@ static void RangeSection (void)
InfoError ("Required values missing from this section");
}
if (CPU == CPU_65816) {
if (Type == atCode && !(Attributes & tAddrMode)) {
InfoError ("65816 code sections require addressing mode");
}
if (Type != atCode && (Attributes & tAddrMode)) {
InfoError ("AddrMode is only valid for code sections");
}
}
/* Start must be less than end */
if (Start > End) {
InfoError ("Start value must not be greater than end value");
@ -672,7 +716,7 @@ static void RangeSection (void)
}
/* Set the range */
MarkRange (Start, End, Type);
MarkRange (Start, End, Type | AddrMode);
/* Do we have a label? */
if (Attributes & tName) {

View File

@ -60,6 +60,12 @@
/* Symbol table */
static const char* SymTab[0x10000];
/* 65816 symbol table */
#define MAX_LONG_LABELS 256
static const char* LongSymVal[MAX_LONG_LABELS];
static unsigned LongSymAddr[MAX_LONG_LABELS];
static unsigned LongLabelsUsed;
/*****************************************************************************/
@ -74,12 +80,27 @@ static const char* MakeLabelName (unsigned Addr)
*/
{
static char LabelBuf [32];
xsprintf (LabelBuf, sizeof (LabelBuf), "L%04X", Addr);
xsprintf (LabelBuf, sizeof (LabelBuf),
IsLongAddr (Addr) ? "L%06X" : "L%04X", Addr);
return LabelBuf;
}
static unsigned FindLongIndex (unsigned Addr)
{
unsigned i;
for (i = 0; i < LongLabelsUsed; i++) {
if (LongSymAddr[i] == Addr) {
return i;
}
}
return -1;
}
static void AddLabel (unsigned Addr, attr_t Attr, const char* Name)
/* Add a label */
{
@ -91,19 +112,41 @@ static void AddLabel (unsigned Addr, attr_t Attr, const char* Name)
/* Allow redefinition if identical. Beware: Unnamed labels don't
** have a name (you guessed that, didn't you?).
*/
if (ExistingAttr == Attr &&
((Name == 0 && SymTab[Addr] == 0) ||
(Name != 0 && SymTab[Addr] != 0 &&
strcmp (SymTab[Addr], Name) == 0))) {
return;
if (IsLongAddr (Addr)) {
const unsigned i = FindLongIndex (Addr);
if (ExistingAttr == Attr &&
((Name == 0 && LongSymVal[i] == 0) ||
(Name != 0 && LongSymVal[i] != 0 &&
strcmp (LongSymVal[i], Name) == 0))) {
return;
}
Error ("Duplicate label for address $%06X (%s): '%s'", Addr,
LongSymVal[i] == 0 ? "<unnamed label>" : LongSymVal[i],
Name == 0 ? "<unnamed label>" : Name);
} else {
if (ExistingAttr == Attr &&
((Name == 0 && SymTab[Addr] == 0) ||
(Name != 0 && SymTab[Addr] != 0 &&
strcmp (SymTab[Addr], Name) == 0))) {
return;
}
Error ("Duplicate label for address $%04X (%s): '%s'", Addr,
SymTab[Addr] == 0 ? "<unnamed label>" : SymTab[Addr],
Name == 0 ? "<unnamed label>" : Name);
}
Error ("Duplicate label for address $%04X (%s): '%s'", Addr,
SymTab[Addr] == 0 ? "<unnamed label>" : SymTab[Addr],
Name == 0 ? "<unnamed label>" : Name);
}
/* Create a new label (xstrdup will return NULL if input NULL) */
SymTab[Addr] = xstrdup (Name);
if (IsLongAddr (Addr)) {
if (LongLabelsUsed >= MAX_LONG_LABELS) {
Error ("Too many long labels");
}
LongSymAddr[LongLabelsUsed] = Addr;
LongSymVal[LongLabelsUsed] = xstrdup (Name);
LongLabelsUsed++;
} else {
SymTab[Addr] = xstrdup (Name);
}
/* Remember the attribute */
MarkAddr (Addr, Attr);
@ -254,6 +297,10 @@ const char* GetLabelName (unsigned Addr)
*/
if (A == atUnnamedLabel) {
return "";
} else if (IsLongAddr (Addr)) {
/* Return the label if any */
const unsigned i = FindLongIndex (Addr);
return i < LongLabelsUsed ? LongSymVal[i] : NULL;
} else {
/* Return the label if any */
return SymTab[Addr];
@ -327,6 +374,10 @@ const char* GetLabel (unsigned Addr, unsigned RefFrom)
return FwdLabels[Count-1];
}
} else if (IsLongAddr (Addr)) {
/* Return the label if any */
const unsigned i = FindLongIndex (Addr);
return i < LongLabelsUsed ? LongSymVal[i] : NULL;
} else {
/* Return the label if any */
return SymTab[Addr];
@ -371,7 +422,13 @@ static void DefOutOfRangeLabel (unsigned long Addr)
case atIntLabel:
case atExtLabel:
DefConst (SymTab[Addr], GetComment (Addr), Addr);
if (IsLongAddr (Addr)) {
const unsigned i = FindLongIndex (Addr);
DefConst (i < LongLabelsUsed ? LongSymVal[i] : NULL,
GetComment (Addr), Addr);
} else {
DefConst (SymTab[Addr], GetComment (Addr), Addr);
}
break;
case atUnnamedLabel:
@ -390,6 +447,7 @@ void DefOutOfRangeLabels (void)
/* Output any labels that are out of the loaded code range */
{
unsigned long Addr;
unsigned i;
SeparatorLine ();
@ -412,5 +470,10 @@ void DefOutOfRangeLabels (void)
DefOutOfRangeLabel (Addr++);
}
/* 65816 long range */
for (i = 0; i < LongLabelsUsed; i++) {
DefOutOfRangeLabel (LongSymAddr[i]);
}
SeparatorLine ();
}

View File

@ -55,6 +55,7 @@
#include "data.h"
#include "error.h"
#include "global.h"
#include "handler.h"
#include "infofile.h"
#include "labels.h"
#include "opctable.h"
@ -63,6 +64,8 @@
#include "segment.h"
static unsigned PrevAddrMode;
/*****************************************************************************/
/* Code */
@ -427,8 +430,13 @@ static void OneOpcode (unsigned RemainingBytes)
switch (Style) {
case atDefault:
D->Handler (D);
PC += D->Size;
if (CPU == CPU_65816) {
DataByteLine (1);
++PC;
} else {
D->Handler (D);
PC += D->Size;
}
break;
case atCode:
@ -436,12 +444,36 @@ static void OneOpcode (unsigned RemainingBytes)
** following insn, fall through to byte mode.
*/
if (D->Size <= RemainingBytes) {
if (CPU == CPU_65816) {
const unsigned AddrMode = GetAttr (PC) & at65816Mask;
if (PrevAddrMode != AddrMode) {
if ((PrevAddrMode & atMem8) != (AddrMode & atMem8) ||
(PrevAddrMode & atMem16) != (AddrMode & atMem16)) {
OutputMFlag(!!(AddrMode & atMem8));
}
if ((PrevAddrMode & atIdx8) != (AddrMode & atIdx8) ||
(PrevAddrMode & atIdx16) != (AddrMode & atIdx16)) {
OutputXFlag(!!(AddrMode & atIdx8));
}
PrevAddrMode = AddrMode;
}
}
/* Output labels within the next insn */
for (I = 1; I < D->Size; ++I) {
ForwardLabel (I);
}
/* Output the insn */
D->Handler (D);
if (CPU == CPU_65816 && (D->Flags & flSizeChanges)) {
if ((D->Handler == OH_Immediate65816M &&
GetAttr (PC) & atMem16) ||
(D->Handler == OH_Immediate65816X &&
GetAttr (PC) & atIdx16)) {
PC++;
}
}
PC += D->Size;
break;
}
@ -503,6 +535,8 @@ static void OnePass (void)
{
unsigned Count;
PrevAddrMode = 0;
/* Disassemble until nothing left */
while ((Count = GetRemainingBytes()) > 0) {
OneOpcode (Count);

View File

@ -56,13 +56,13 @@ const OpcDesc OpcTable_65816[256] = {
{ "asl", 2, flUseLabel, OH_Direct }, /* $06 */
{ "ora", 2, flUseLabel, OH_DirectIndirectLong }, /* $07 */
{ "php", 1, flNone, OH_Implicit }, /* $08 */
{ "ora", 2, flNone, OH_Immediate }, /* $09 */
{ "ora", 2, flSizeChanges, OH_Immediate65816M }, /* $09 */
{ "asl", 1, flNone, OH_Accumulator }, /* $0a */
{ "phd", 1, flNone, OH_Implicit }, /* $0b */
{ "tsb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0c */
{ "ora", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0d */
{ "asl", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $0e */
{ "ora", 4, flUseLabel, OH_AbsoluteLong }, /* $0f */
{ "ora", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $0f */
{ "bpl", 2, flLabel, OH_Relative }, /* $10 */
{ "ora", 2, flUseLabel, OH_DirectIndirectY }, /* $11 */
{ "ora", 2, flUseLabel, OH_DirectIndirect }, /* $12 */
@ -78,23 +78,23 @@ const OpcDesc OpcTable_65816[256] = {
{ "trb", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $1c */
{ "ora", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1d */
{ "asl", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $1e */
{ "ora", 4, flUseLabel, OH_AbsoluteLongX }, /* $1f */
{ "ora", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $1f */
{ "jsr", 3, flLabel, OH_JsrAbsolute }, /* $20 */
{ "and", 2, flUseLabel, OH_DirectXIndirect }, /* $21 */
{ "jsl", 3, flLabel, OH_AbsoluteLong }, /* $22 */
{ "jsl", 4, flLabel|flFarOverride, OH_AbsoluteLong }, /* $22 */
{ "and", 2, flNone, OH_StackRelative }, /* $23 */
{ "bit", 2, flUseLabel, OH_Direct }, /* $24 */
{ "and", 2, flUseLabel, OH_Direct }, /* $25 */
{ "rol", 2, flUseLabel, OH_Direct }, /* $26 */
{ "and", 2, flUseLabel, OH_DirectIndirectLong }, /* $27 */
{ "plp", 1, flNone, OH_Implicit }, /* $28 */
{ "and", 2, flNone, OH_Immediate }, /* $29 */
{ "and", 2, flSizeChanges, OH_Immediate65816M }, /* $29 */
{ "rol", 1, flNone, OH_Accumulator }, /* $2a */
{ "pld", 1, flNone, OH_Implicit }, /* $2b */
{ "bit", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2c */
{ "and", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2d */
{ "rol", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $2e */
{ "and", 4, flUseLabel, OH_AbsoluteLong }, /* $2f */
{ "and", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $2f */
{ "bmi", 2, flLabel, OH_Relative }, /* $30 */
{ "and", 2, flUseLabel, OH_DirectIndirectY }, /* $31 */
{ "and", 2, flUseLabel, OH_DirectIndirect }, /* $32 */
@ -110,28 +110,28 @@ const OpcDesc OpcTable_65816[256] = {
{ "bit", 3, flUseLabel, OH_AbsoluteX }, /* $3c */
{ "and", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3d */
{ "rol", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $3e */
{ "and", 4, flUseLabel, OH_AbsoluteLongX }, /* $3f */
{ "and", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $3f */
{ "rti", 1, flNone, OH_Rts }, /* $40 */
{ "eor", 2, flUseLabel, OH_DirectXIndirect }, /* $41 */
{ "wdm", 2, flNone, OH_Implicit }, /* $42 */
{ "eor", 2, flNone, OH_StackRelative }, /* $43 */
{ "mvp", 3, flNone, OH_BlockMove }, /* $44 */
{ "mvp", 3, flNone, OH_BlockMove65816 }, /* $44 */
{ "eor", 2, flUseLabel, OH_Direct }, /* $45 */
{ "lsr", 2, flUseLabel, OH_Direct }, /* $46 */
{ "eor", 2, flUseLabel, OH_DirectIndirectLong }, /* $47 */
{ "pha", 1, flNone, OH_Implicit }, /* $48 */
{ "eor", 2, flNone, OH_Immediate }, /* $49 */
{ "eor", 2, flSizeChanges, OH_Immediate65816M }, /* $49 */
{ "lsr", 1, flNone, OH_Accumulator }, /* $4a */
{ "phk", 1, flNone, OH_Implicit }, /* $4b */
{ "jmp", 3, flLabel, OH_JmpAbsolute }, /* $4c */
{ "eor", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4d */
{ "lsr", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $4e */
{ "eor", 4, flUseLabel, OH_AbsoluteLong }, /* $4f */
{ "eor", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $4f */
{ "bvc", 2, flLabel, OH_Relative }, /* $50 */
{ "eor", 2, flUseLabel, OH_DirectIndirectY }, /* $51 */
{ "eor", 2, flUseLabel, OH_DirectIndirect }, /* $52 */
{ "eor", 2, flNone, OH_StackRelativeIndirectY}, /* $53 */
{ "mvn", 3, flNone, OH_BlockMove }, /* $54 */
{ "mvn", 3, flNone, OH_BlockMove65816 }, /* $54 */
{ "eor", 2, flUseLabel, OH_DirectX }, /* $55 */
{ "lsr", 2, flUseLabel, OH_DirectX }, /* $56 */
{ "eor", 2, flUseLabel, OH_DirectIndirectLongY }, /* $57 */
@ -139,10 +139,10 @@ const OpcDesc OpcTable_65816[256] = {
{ "eor", 3, flUseLabel, OH_AbsoluteY }, /* $59 */
{ "phy", 1, flNone, OH_Implicit }, /* $5a */
{ "tcd", 1, flNone, OH_Implicit }, /* $5b */
{ "jml", 4, flLabel, OH_AbsoluteLong }, /* $5c */
{ "jml", 4, flLabel|flFarOverride, OH_AbsoluteLong }, /* $5c */
{ "eor", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5d */
{ "lsr", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $5e */
{ "eor", 4, flUseLabel, OH_AbsoluteLongX }, /* $5f */
{ "eor", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $5f */
{ "rts", 1, flNone, OH_Rts }, /* $60 */
{ "adc", 2, flUseLabel, OH_DirectXIndirect }, /* $61 */
{ "per", 3, flLabel, OH_RelativeLong }, /* $62 */
@ -152,13 +152,13 @@ const OpcDesc OpcTable_65816[256] = {
{ "ror", 2, flUseLabel, OH_Direct }, /* $66 */
{ "adc", 2, flUseLabel, OH_DirectIndirectLong }, /* $67 */
{ "pla", 1, flNone, OH_Implicit }, /* $68 */
{ "adc", 2, flNone, OH_Immediate }, /* $69 */
{ "adc", 2, flSizeChanges, OH_Immediate65816M }, /* $69 */
{ "ror", 1, flNone, OH_Accumulator }, /* $6a */
{ "rtl", 1, flNone, OH_Implicit }, /* $6b */
{ "jmp", 3, flLabel, OH_JmpAbsoluteIndirect }, /* $6c */
{ "adc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6d */
{ "ror", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $6e */
{ "adc", 4, flUseLabel, OH_AbsoluteLong }, /* $6f */
{ "adc", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $6f */
{ "bvs", 2, flLabel, OH_Relative }, /* $70 */
{ "adc", 2, flUseLabel, OH_DirectIndirectY }, /* $71 */
{ "adc", 2, flUseLabel, OH_DirectIndirect }, /* $72 */
@ -174,7 +174,7 @@ const OpcDesc OpcTable_65816[256] = {
{ "jmp", 3, flLabel, OH_AbsoluteXIndirect }, /* $7c */
{ "adc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7d */
{ "ror", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $7e */
{ "adc", 4, flUseLabel, OH_AbsoluteLongX }, /* $7f */
{ "adc", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $7f */
{ "bra", 2, flLabel, OH_Relative }, /* $80 */
{ "sta", 2, flUseLabel, OH_DirectXIndirect }, /* $81 */
{ "brl", 3, flLabel, OH_RelativeLong }, /* $82 */
@ -184,13 +184,13 @@ const OpcDesc OpcTable_65816[256] = {
{ "stx", 2, flUseLabel, OH_Direct }, /* $86 */
{ "sta", 2, flUseLabel, OH_DirectIndirectLong }, /* $87 */
{ "dey", 1, flNone, OH_Implicit }, /* $88 */
{ "bit", 2, flNone, OH_Immediate }, /* $89 */
{ "bit", 2, flSizeChanges, OH_Immediate65816M }, /* $89 */
{ "txa", 1, flNone, OH_Implicit }, /* $8a */
{ "phb", 1, flNone, OH_Implicit }, /* $8b */
{ "sty", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8c */
{ "sta", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8d */
{ "stx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $8e */
{ "sta", 4, flUseLabel, OH_AbsoluteLong }, /* $8f */
{ "sta", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $8f */
{ "bcc", 2, flLabel, OH_Relative }, /* $90 */
{ "sta", 2, flUseLabel, OH_DirectIndirectY }, /* $91 */
{ "sta", 2, flUseLabel, OH_DirectIndirect }, /* $92 */
@ -206,23 +206,23 @@ const OpcDesc OpcTable_65816[256] = {
{ "stz", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $9c */
{ "sta", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9d */
{ "stz", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $9e */
{ "sta", 4, flUseLabel, OH_AbsoluteLongX }, /* $9f */
{ "ldy", 2, flNone, OH_Immediate }, /* $a0 */
{ "sta", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $9f */
{ "ldy", 2, flSizeChanges, OH_Immediate65816X }, /* $a0 */
{ "lda", 2, flUseLabel, OH_DirectXIndirect }, /* $a1 */
{ "ldx", 2, flNone, OH_Immediate }, /* $a2 */
{ "ldx", 2, flSizeChanges, OH_Immediate65816X }, /* $a2 */
{ "lda", 2, flNone, OH_StackRelative }, /* $a3 */
{ "ldy", 2, flUseLabel, OH_Direct }, /* $a4 */
{ "lda", 2, flUseLabel, OH_Direct }, /* $a5 */
{ "ldx", 2, flUseLabel, OH_Direct }, /* $a6 */
{ "lda", 2, flUseLabel, OH_DirectIndirectLong }, /* $a7 */
{ "tay", 1, flNone, OH_Implicit }, /* $a8 */
{ "lda", 2, flNone, OH_Immediate }, /* $a9 */
{ "lda", 2, flSizeChanges, OH_Immediate65816M }, /* $a9 */
{ "tax", 1, flNone, OH_Implicit }, /* $aa */
{ "plb", 1, flNone, OH_Implicit }, /* $ab */
{ "ldy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ac */
{ "lda", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ad */
{ "ldx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ae */
{ "lda", 4, flUseLabel, OH_AbsoluteLong }, /* $af */
{ "lda", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $af */
{ "bcs", 2, flLabel, OH_Relative }, /* $b0 */
{ "lda", 2, flUseLabel, OH_DirectIndirectY }, /* $b1 */
{ "lda", 2, flUseLabel, OH_DirectIndirect }, /* $b2 */
@ -238,8 +238,8 @@ const OpcDesc OpcTable_65816[256] = {
{ "ldy", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bc */
{ "lda", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $bd */
{ "ldx", 3, flUseLabel|flAbsOverride, OH_AbsoluteY }, /* $be */
{ "lda", 4, flUseLabel, OH_AbsoluteLongX }, /* $bf */
{ "cpy", 2, flNone, OH_Immediate }, /* $c0 */
{ "lda", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $bf */
{ "cpy", 2, flSizeChanges, OH_Immediate65816X }, /* $c0 */
{ "cmp", 2, flUseLabel, OH_DirectXIndirect }, /* $c1 */
{ "rep", 2, flNone, OH_Immediate }, /* $c2 */
{ "cmp", 2, flNone, OH_StackRelative }, /* $c3 */
@ -248,18 +248,18 @@ const OpcDesc OpcTable_65816[256] = {
{ "dec", 2, flUseLabel, OH_Direct }, /* $c6 */
{ "cmp", 2, flUseLabel, OH_DirectIndirectLong }, /* $c7 */
{ "iny", 1, flNone, OH_Implicit }, /* $c8 */
{ "cmp", 2, flNone, OH_Immediate }, /* $c9 */
{ "cmp", 2, flSizeChanges, OH_Immediate65816M }, /* $c9 */
{ "dex", 1, flNone, OH_Implicit }, /* $ca */
{ "wai", 1, flNone, OH_Implicit }, /* $cb */
{ "cpy", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cc */
{ "cmp", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $cd */
{ "dec", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ce */
{ "cmp", 4, flUseLabel, OH_AbsoluteLong }, /* $cf */
{ "cmp", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $cf */
{ "bne", 2, flLabel, OH_Relative }, /* $d0 */
{ "cmp", 2, flUseLabel, OH_DirectIndirectY }, /* $d1 */
{ "cmp", 2, flUseLabel, OH_DirectIndirect }, /* $d2 */
{ "cmp", 2, flNone, OH_StackRelativeIndirectY}, /* $d3 */
{ "pei", 2, flUseLabel, OH_Direct }, /* $d4 */
{ "pei", 2, flUseLabel, OH_DirectIndirect }, /* $d4 */
{ "cmp", 2, flUseLabel, OH_DirectX }, /* $d5 */
{ "dec", 2, flUseLabel, OH_DirectX }, /* $d6 */
{ "cmp", 2, flUseLabel, OH_DirectIndirectLongY }, /* $d7 */
@ -270,8 +270,8 @@ const OpcDesc OpcTable_65816[256] = {
{ "jml", 3, flLabel, OH_AbsoluteIndirect }, /* $dc */
{ "cmp", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $dd */
{ "dec", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $de */
{ "cmp", 4, flUseLabel, OH_AbsoluteLongX }, /* $df */
{ "cpx", 2, flNone, OH_Immediate }, /* $e0 */
{ "cmp", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $df */
{ "cpx", 2, flSizeChanges, OH_Immediate65816X }, /* $e0 */
{ "sbc", 2, flUseLabel, OH_DirectXIndirect }, /* $e1 */
{ "sep", 2, flNone, OH_Immediate }, /* $e2 */
{ "sbc", 2, flNone, OH_StackRelative }, /* $e3 */
@ -280,13 +280,13 @@ const OpcDesc OpcTable_65816[256] = {
{ "inc", 2, flUseLabel, OH_Direct }, /* $e6 */
{ "sbc", 2, flUseLabel, OH_DirectIndirectLong }, /* $e7 */
{ "inx", 1, flNone, OH_Implicit }, /* $e8 */
{ "sbc", 2, flNone, OH_Immediate }, /* $e9 */
{ "sbc", 2, flSizeChanges, OH_Immediate65816M }, /* $e9 */
{ "nop", 1, flNone, OH_Implicit }, /* $ea */
{ "xba", 1, flNone, OH_Implicit }, /* $eb */
{ "cpx", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ec */
{ "sbc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ed */
{ "inc", 3, flUseLabel|flAbsOverride, OH_Absolute }, /* $ee */
{ "sbc", 4, flUseLabel, OH_AbsoluteLong }, /* $ef */
{ "sbc", 4, flUseLabel|flFarOverride, OH_AbsoluteLong }, /* $ef */
{ "beq", 2, flLabel, OH_Relative }, /* $f0 */
{ "sbc", 2, flUseLabel, OH_DirectIndirectY }, /* $f1 */
{ "sbc", 2, flUseLabel, OH_DirectIndirect }, /* $f2 */
@ -302,5 +302,5 @@ const OpcDesc OpcTable_65816[256] = {
{ "jsr", 3, flLabel, OH_AbsoluteXIndirect }, /* $fc */
{ "sbc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fd */
{ "inc", 3, flUseLabel|flAbsOverride, OH_AbsoluteX }, /* $fe */
{ "sbc", 4, flUseLabel, OH_AbsoluteLongX }, /* $ff */
{ "sbc", 4, flUseLabel|flFarOverride, OH_AbsoluteLongX }, /* $ff */
};

View File

@ -53,7 +53,8 @@ enum {
flLabel = flUseLabel|flGenLabel, /* Generate and use a label */
flIllegal = 0x10, /* Illegal instruction */
flAbsOverride = 0x20, /* Need a: override */
flFarOverride = 0x40 /* Need f: override */
flFarOverride = 0x40, /* Need f: override */
flSizeChanges = 0x80 /* 65816: size may change */
};
/* Forward/typedef for struct OpcDesc */

View File

@ -74,6 +74,7 @@ void SetOpcTable (cpu_t CPU)
case CPU_6502DTV: OpcTable = OpcTable_6502DTV; break;
case CPU_65SC02: OpcTable = OpcTable_65SC02; break;
case CPU_65C02: OpcTable = OpcTable_65C02; break;
case CPU_65816: OpcTable = OpcTable_65816; break;
case CPU_HUC6280: OpcTable = OpcTable_HuC6280; break;
case CPU_M740: OpcTable = OpcTable_M740; break;
case CPU_4510: OpcTable = OpcTable_4510; break;

View File

@ -401,3 +401,23 @@ void OutputSettings (void)
LineFeed ();
LineFeed ();
}
void OutputMFlag (unsigned char enabled)
/* Output the 65816 M-flag state */
{
Indent (MCol);
Output (enabled ? ".a8" : ".a16");
LineFeed ();
}
void OutputXFlag (unsigned char enabled)
/* Output the 65816 X-flag state */
{
Indent (MCol);
Output (enabled ? ".i8" : ".i16");
LineFeed ();
}

View File

@ -108,6 +108,12 @@ void LineComment (unsigned PC, unsigned Count);
void OutputSettings (void);
/* Output CPU and other settings */
void OutputMFlag (unsigned char enabled);
/* Output the 65816 M-flag state */
void OutputXFlag (unsigned char enabled);
/* Output the 65816 X-flag state */
/* End of output.h */

View File

@ -90,6 +90,7 @@ typedef enum token_t {
INFOTOK_START,
INFOTOK_END,
INFOTOK_TYPE,
INFOTOK_ADDRMODE,
INFOTOK_CODE,
INFOTOK_BYTETAB,

7
test/dasm/65816.cfg Normal file
View File

@ -0,0 +1,7 @@
MEMORY {
ROM: start = $8000, size = $8000;
}
SEGMENTS {
CODE: load = ROM;
}

7
test/dasm/65816.info Normal file
View File

@ -0,0 +1,7 @@
GLOBAL {
startaddr $8000;
};
RANGE { START $8000; END $8229; ADDRMODE "MX"; TYPE Code;};
RANGE { START $822a; END $824b; ADDRMODE "mx"; TYPE Code;};

View File

@ -19,6 +19,8 @@ ifdef QUIET
endif
CL65 := $(if $(wildcard ../../bin/cl65*),../../bin/cl65,cl65)
CA65 := $(if $(wildcard ../../bin/ca65*),../../bin/ca65,ca65)
LD65 := $(if $(wildcard ../../bin/ld65*),../../bin/ld65,ld65)
DA65 := $(if $(wildcard ../../bin/da65*),../../bin/da65,da65)
WORKDIR = ../../testwrk/dasm
@ -33,7 +35,7 @@ START = --start-addr 0x8000
.PHONY: all clean
SOURCES := $(wildcard *.s)
BINS = $(SOURCES:%disass.s=$(WORKDIR)/%reass.bin)
BINS = $(SOURCES:%disass.s=$(WORKDIR)/%reass.bin) $(WORKDIR)/65816-reass.bin
CPUS = $(SOURCES:%-disass.s=%)
all: $(BINS)
@ -61,5 +63,18 @@ endef # DISASS_template
$(foreach cpu,$(CPUS),$(eval $(call DISASS_template,$(cpu))))
$(WORKDIR)/test65816.bin: test65816.s | $(WORKDIR)
$(CA65) -o $(WORKDIR)/test65816.o $<
$(LD65) -o $@ -C 65816.cfg $(WORKDIR)/test65816.o
$(WORKDIR)/65816-reass.s: $(WORKDIR)/test65816.bin
$(DA65) --cpu 65816 -i 65816.info -o $@ $<
$(WORKDIR)/65816-reass.bin: $(WORKDIR)/65816-reass.s $(ISEQUAL)
$(if $(QUIET),echo dasm/65816-reass.bin)
$(CA65) -o $(WORKDIR)/65816-reass.o $<
$(LD65) -o $@ -C 65816.cfg $(WORKDIR)/65816-reass.o
$(ISEQUAL) --binary $(WORKDIR)/test65816.bin $@
clean:
@$(call RMDIR,$(WORKDIR))

273
test/dasm/test65816.s Normal file
View File

@ -0,0 +1,273 @@
.setcpu "65816"
ADC ($10,X)
ADC $32,S
ADC $10
ADC [$10]
ADC #$54
ADC $9876
ADC $FEDBCA
ADC ($10),Y
ADC ($10)
ADC ($32,S),Y
ADC $10,X
ADC [$10],Y
ADC $9876,Y
ADC $9876,X
ADC $FEDCBA,X
SBC ($10,X)
SBC $32,S
SBC $10
SBC [$10]