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]
SBC #$54
SBC $9876
SBC $FEDBCA
SBC ($10),Y
SBC ($10)
SBC ($32,S),Y
SBC $10,X
SBC [$10],Y
SBC $9876,Y
SBC $9876,X
SBC $FEDCBA,X
CMP ($10,X)
CMP $32,S
CMP $10
CMP [$10]
CMP #$54
CMP $9876
CMP $FEDBCA
CMP ($10),Y
CMP ($10)
CMP ($32,S),Y
CMP $10,X
CMP [$10],Y
CMP $9876,Y
CMP $9876,X
CMP $FEDCBA,X
CPX #$54
CPX $10
CPX $9876
CPY #$54
CPY $10
CPY $9876
DEC
DEC $10
DEC $9876
DEC $10,X
DEC $9876,X
DEX
DEY
INC
INC $10
INC $9876
INC $10,X
INC $9876,X
INX
INY
AND ($10,X)
AND $32,S
AND $10
AND [$10]
AND #$54
AND $9876
AND $FEDBCA
AND ($10),Y
AND ($10)
AND ($32,S),Y
AND $10,X
AND [$10],Y
AND $9876,Y
AND $9876,X
AND $FEDCBA,X
EOR ($10,X)
EOR $32,S
EOR $10
EOR [$10]
EOR #$54
EOR $9876
EOR $FEDBCA
EOR ($10),Y
EOR ($10)
EOR ($32,S),Y
EOR $10,X
EOR [$10],Y
EOR $9876,Y
EOR $9876,X
EOR $FEDCBA,X
ORA ($10,X)
ORA $32,S
ORA $10
ORA [$10]
ORA #$54
ORA $9876
ORA $FEDBCA
ORA ($10),Y
ORA ($10)
ORA ($32,S),Y
ORA $10,X
ORA [$10],Y
ORA $9876,Y
ORA $9876,X
ORA $FEDCBA,X
BIT $10
BIT $9876
BIT $10,X
BIT $9876,X
BIT #$54
TRB $10
TRB $9876
TSB $10
TSB $9876
ASL $10
ASL
ASL $9876
ASL $10,X
ASL $9876,X
LSR $10
LSR
LSR $9876
LSR $10,X
LSR $9876,X
ROL $10
ROL
ROL $9876
ROL $10,X
ROL $9876,X
ROR $10
ROR
ROR $9876
ROR $10,X
ROR $9876,X
LABEL:
BCC LABEL
BCS LABEL
BEQ LABEL
BMI LABEL
BNE LABEL
BPL LABEL
BRA LABEL
BVC LABEL
BVS LABEL
BRL LABEL
JMP $1234
JMP $FEDCBA
JMP ($1234)
JMP ($1234,X)
JMP [$1234]
JSL $123456
JSR $1234
JSR ($1234,X)
RTL
RTS
BRK
RTI
CLC
CLD
CLI
CLV
SEC
SED
SEI
REP #$12
SEP #$12
LDA ($10,X)
LDA $32,S
LDA $10
LDA [$10]
LDA #$54
LDA $9876
LDA $FEDBCA
LDA ($10),Y
LDA ($10)
LDA ($32,S),Y
LDA $10,X
LDA [$10],Y
LDA $9876,Y
LDA $9876,X
LDA $FEDCBA,X
LDX #$54
LDX $10
LDX $9876
LDX $10,Y
LDX $9876,Y
LDY #$54
LDY $10
LDY $9876
LDY $10,X
LDY $9876,X
STA ($10,X)
STA $32,S
STA $10
STA [$10]
STA $9876
STA $FEDBCA
STA ($10),Y
STA ($10)
STA ($32,S),Y
STA $10,X
STA [$10],Y
STA $9876,Y
STA $9876,X
STA $FEDCBA,X
STX $10
STX $9876
STX $10,Y
STY $10
STY $9876
STY $10,X
STZ $10
STZ $10,X
STZ $9876
STZ $9876,X
MVN #$12,#$34
MVP #$12,#$34
NOP
PEA $1234
PEI ($12)
PER LABEL
PHA
PHX
PHY
PLA
PLX
PLY
PHB
PHD
PHK
PHP
PLB
PLD
PLP
STP
WAI
TAX
TAY
TSX
TXA
TXS
TXY
TYA
TYX
TCD
TCS
TDC
TSC
XBA
XCE
.a16
.i16
longs:
ADC #$5432
SBC #$5432
CMP #$5432
CPX #$5432
CPY #$5432
AND #$5432
EOR #$5432
ORA #$5432
BIT #$5432
LDA #$5432
LDX #$5432
LDY #$5432

61
util/parse-bsnes-log.awk Executable file
View File

@ -0,0 +1,61 @@
#!/usr/bin/awk -nf
#
# Parse the bsnes-plus cpu log for the 65816 address mode ranges.
# Since the log doesn't show the op size, we have to be careful
# and add +3 to the range end - this may need manual cleanup.
#
# Grep the input for only one bank's content beforehand.
#
# (C) Lauri Kasanen, under the cc65 license
#
{
addr = $1
IGNORECASE = 1
if ($9 ~ /^nv/) {
val = $9
} else if ($10 ~ /^nv/) {
val = $10
} else {
val = $11
}
IGNORECASE = 0
val = substr(val, 3, 2)
if (val == "1B") # emulation mode
val = "MX"
addrs["0x" substr(addr, 3)] = val
}
END {
PROCINFO["sorted_in"] = "@ind_num_asc"
start = -1
prevval = ""
for (addr in addrs) {
cur = addrs[addr]
if (start == -1) { # first range
start = addr
} else {
if (prevval != cur || addr - prevaddr > 4) { # start a new range
#print "diff " addr - prevaddr ", addr " addr ", pa " prevaddr
if (prevaddr + 3 >= addr + 0)
fmt = sprintf("%04x", addr - 1)
else
fmt = sprintf("%04x", prevaddr + 3)
print "RANGE { START $" substr(start, 3) "; END $" fmt "; ADDRMODE \"" prevval "\"; TYPE Code;};"
start = addr
}
}
#print "\t" addr " " addrs[addr]
prevval = cur
prevaddr = addr
}
fmt = sprintf("%04x", prevaddr + 3)
print "RANGE { START $" substr(start, 3) "; END $" fmt "; ADDRMODE \"" prevval "\"; TYPE Code;};"
}