Skip to content

Commit cce119a

Browse files
authored
Merge pull request cc65#1871 from clbr/da816
da65 support for 65816
2 parents de30a57 + 9aae1ef commit cce119a

22 files changed

+834
-85
lines changed

doc/da65.sgml

+24-4
Original file line numberDiff line numberDiff line change
@@ -115,14 +115,14 @@ Here is a description of all the command line options:
115115
<item>6502dtv
116116
<item>65sc02
117117
<item>65c02
118+
<item>65816
118119
<item>huc6280
119120
<item>4510
120121
</itemize>
121122

122123
6502x is for the NMOS 6502 with unofficial opcodes. 6502dtv is for the
123124
emulated CPU of the C64DTV device. huc6280 is the CPU of the PC engine.
124-
4510 is the CPU of the Commodore C65. Support for the 65816 currently
125-
is not available.
125+
4510 is the CPU of the Commodore C65. 65816 is the CPU of the SNES.
126126

127127

128128
<label id="option--formfeeds">
@@ -263,8 +263,9 @@ can produce output that can not be re-assembled, when one or more of those
263263
branches point outside of the disassembled memory. This can happen when text
264264
or binary data is processed.
265265

266-
While there is some code for the 65816 in the sources, it is currently
267-
unsupported.
266+
The 65816 support requires annotating ranges with the M and X flag states.
267+
This can be recorded with an emulator that supports Code and Data Logging,
268+
for example. Disassemble one bank at a time.
268269

269270

270271
<sect1>Attribute map<p>
@@ -521,6 +522,11 @@ following attributes are recognized:
521522

522523
</descrip>
523524

525+
<tag><tt>ADDRMODE</tt></tag>
526+
When disassembling 65816 code, this specifies the M and X flag states
527+
for this range. It's a string argument of the form "mx", capital letters
528+
mean the flag is enabled.
529+
524530
</descrip>
525531

526532

@@ -693,6 +699,20 @@ directives explained above:
693699

694700

695701

702+
<sect>Helper scripts<p>
703+
704+
<tt>util/parse-bsnes-log.awk</tt> is a supplied script for 65816 disassembly,
705+
to parse bsnes-plus Code-Data log files and output the RANGE sections
706+
for your info file. For typical usage, you'd check the S-CPU log and trace
707+
log mask boxes in the bsnes-plus debugger, play through the game, then grep
708+
for the bank you're disassembling, and pass that to this script.
709+
710+
<tscreen><verb>
711+
grep ^83 my-game-log | parse-bsnes-log.awk
712+
</verb></tscreen>
713+
714+
715+
696716
<sect>Copyright<p>
697717

698718
da65 (and all cc65 binutils) is (C) Copyright 1998-2011, Ullrich von

src/da65/attrtab.c

+55-3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535

3636
/* da65 */
37+
#include "cpu.h"
3738
#include "error.h"
3839
#include "attrtab.h"
3940

@@ -48,6 +49,12 @@
4849
/* Attribute table */
4950
static unsigned short AttrTab[0x10000];
5051

52+
/* 65816 attribute table */
53+
#define MAX_LONG_ATTRS 256
54+
static unsigned short LongAttrVal[MAX_LONG_ATTRS];
55+
static unsigned LongAttrAddr[MAX_LONG_ATTRS];
56+
static unsigned LongAttrsUsed;
57+
5158

5259

5360
/*****************************************************************************/
@@ -59,19 +66,37 @@ static unsigned short AttrTab[0x10000];
5966
void AddrCheck (unsigned Addr)
6067
/* Check if the given address has a valid range */
6168
{
62-
if (Addr >= 0x10000) {
69+
if (Addr >= 0x10000 && CPU != CPU_65816) {
6370
Error ("Address out of range: %08X", Addr);
6471
}
6572
}
6673

6774

75+
unsigned char IsLongAddr (unsigned Addr)
76+
/* Is it 24-bit? */
77+
{
78+
return Addr >= 0x10000 && CPU == CPU_65816;
79+
}
80+
81+
6882

6983
attr_t GetAttr (unsigned Addr)
7084
/* Return the attribute for the given address */
7185
{
7286
/* Check the given address */
7387
AddrCheck (Addr);
7488

89+
if (IsLongAddr (Addr)) {
90+
unsigned i;
91+
for (i = 0; i < LongAttrsUsed; i++) {
92+
if (LongAttrAddr[i] == Addr) {
93+
return LongAttrVal[i];
94+
}
95+
}
96+
97+
return 0;
98+
}
99+
75100
/* Return the attribute */
76101
return AttrTab[Addr];
77102
}
@@ -148,6 +173,33 @@ void MarkAddr (unsigned Addr, attr_t Attr)
148173
/* Check the given address */
149174
AddrCheck (Addr);
150175

176+
if (IsLongAddr (Addr)) {
177+
unsigned i;
178+
for (i = 0; i < LongAttrsUsed; i++) {
179+
if (LongAttrAddr[i] == Addr) {
180+
181+
/* We must not have more than one style bit */
182+
if (Attr & atStyleMask) {
183+
if (LongAttrVal[i] & atStyleMask) {
184+
Error ("Duplicate style for long address %06X", Addr);
185+
}
186+
}
187+
LongAttrVal[i] |= Attr;
188+
189+
return;
190+
}
191+
}
192+
193+
if (LongAttrsUsed >= MAX_LONG_ATTRS) {
194+
Error ("Too many long addresses");
195+
}
196+
LongAttrVal[LongAttrsUsed] |= Attr;
197+
LongAttrAddr[LongAttrsUsed] = Addr;
198+
LongAttrsUsed++;
199+
200+
return;
201+
}
202+
151203
/* We must not have more than one style bit */
152204
if (Attr & atStyleMask) {
153205
if (AttrTab[Addr] & atStyleMask) {
@@ -168,7 +220,7 @@ attr_t GetStyleAttr (unsigned Addr)
168220
AddrCheck (Addr);
169221

170222
/* Return the attribute */
171-
return (AttrTab[Addr] & atStyleMask);
223+
return (GetAttr (Addr) & atStyleMask);
172224
}
173225

174226

@@ -180,5 +232,5 @@ attr_t GetLabelAttr (unsigned Addr)
180232
AddrCheck (Addr);
181233

182234
/* Return the attribute */
183-
return (AttrTab[Addr] & atLabelMask);
235+
return (GetAttr (Addr) & atLabelMask);
184236
}

src/da65/attrtab.h

+15-5
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,22 @@ typedef enum attr_t {
6666
atDepLabel = 0x0040, /* Dependent label */
6767
atUnnamedLabel = 0x0080, /* Unnamed label */
6868

69-
atLabelDefined = 0x0100, /* True if we defined the label */
70-
71-
atStyleMask = 0x000F, /* Output style */
72-
atLabelMask = 0x00F0, /* Label information */
73-
7469
/* Segment */
7570
atSegment = 0x0100, /* Code is in a segment */
7671
atSegmentEnd = 0x0200, /* Segment end */
7772
atSegmentStart = 0x0400, /* Segment start */
73+
74+
/* 65816 addressing mode */
75+
atMem8 = 0x1000, /* M flag enabled, 8-bit */
76+
atMem16 = 0x2000, /* M flag disabled, 16-bit */
77+
atIdx8 = 0x4000, /* X flag enabled, 8-bit */
78+
atIdx16 = 0x8000, /* X flag disabled, 16-bit */
79+
80+
atStyleMask = 0x000F, /* Output style */
81+
atLabelMask = 0x00F0, /* Label information */
82+
atSegmentMask = 0x0F00, /* Segment information */
83+
at65816Mask = 0xF000, /* 65816 information */
84+
7885
} attr_t;
7986

8087

@@ -88,6 +95,9 @@ typedef enum attr_t {
8895
void AddrCheck (unsigned Addr);
8996
/* Check if the given address has a valid range */
9097

98+
unsigned char IsLongAddr (unsigned Addr);
99+
/* Check if the given address is 24-bit */
100+
91101
attr_t GetAttr (unsigned Addr);
92102
/* Return the attribute for the given address */
93103

src/da65/code.c

+11
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,17 @@ unsigned long GetCodeDWord (unsigned Addr)
194194

195195

196196

197+
unsigned GetCodeLongAddr (unsigned Addr)
198+
/* Get a word from the given address */
199+
{
200+
unsigned Lo = GetCodeByte (Addr);
201+
unsigned Mid = GetCodeByte (Addr+1);
202+
unsigned Hi = GetCodeByte (Addr+2);
203+
return Lo | (Mid << 8) | (Hi << 16);
204+
}
205+
206+
207+
197208
unsigned GetRemainingBytes (void)
198209
/* Return the number of remaining code bytes */
199210
{

src/da65/code.h

+3
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ unsigned GetCodeWord (unsigned Addr);
7272
unsigned long GetCodeDWord (unsigned Addr);
7373
/* Get a dword from the given address */
7474

75+
unsigned GetCodeLongAddr (unsigned Addr);
76+
/* Get a 24-bit address from the given address */
77+
7578
unsigned GetRemainingBytes (void);
7679
/* Return the number of remaining code bytes */
7780

src/da65/comments.c

+43-4
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@
5252
/* Comment table */
5353
static const char* CommentTab[0x10000];
5454

55+
#define MAX_LONG_COMMENTS 256
56+
static const char* LongCommentVal[MAX_LONG_COMMENTS];
57+
static unsigned LongCommentAddr[MAX_LONG_COMMENTS];
58+
static unsigned LongCommentsUsed;
59+
5560

5661

5762
/*****************************************************************************/
@@ -60,17 +65,43 @@ static const char* CommentTab[0x10000];
6065

6166

6267

68+
static unsigned FindLongIndex (unsigned Addr)
69+
{
70+
unsigned i;
71+
for (i = 0; i < LongCommentsUsed; i++) {
72+
if (LongCommentAddr[i] == Addr) {
73+
return i;
74+
}
75+
}
76+
return -1;
77+
}
78+
79+
80+
6381
void SetComment (unsigned Addr, const char* Comment)
6482
/* Set a comment for the given address */
6583
{
6684
/* Check the given address */
6785
AddrCheck (Addr);
6886

69-
/* If we do already have a comment, warn and ignore the new one */
70-
if (CommentTab[Addr]) {
71-
Warning ("Duplicate comment for address $%04X", Addr);
87+
if (IsLongAddr (Addr)) {
88+
if (FindLongIndex (Addr)) {
89+
Warning ("Duplicate comment for address $%06X", Addr);
90+
} else {
91+
if (LongCommentsUsed >= MAX_LONG_COMMENTS) {
92+
Error("Too many long-address comments");
93+
}
94+
LongCommentVal[LongCommentsUsed] = xstrdup (Comment);
95+
LongCommentAddr[LongCommentsUsed] = Addr;
96+
LongCommentsUsed++;
97+
}
7298
} else {
73-
CommentTab[Addr] = xstrdup (Comment);
99+
/* If we do already have a comment, warn and ignore the new one */
100+
if (CommentTab[Addr]) {
101+
Warning ("Duplicate comment for address $%04X", Addr);
102+
} else {
103+
CommentTab[Addr] = xstrdup (Comment);
104+
}
74105
}
75106
}
76107

@@ -82,6 +113,14 @@ const char* GetComment (unsigned Addr)
82113
/* Check the given address */
83114
AddrCheck (Addr);
84115

116+
if (IsLongAddr (Addr)) {
117+
const unsigned i = FindLongIndex (Addr);
118+
if (i < LongCommentsUsed) {
119+
return LongCommentVal[i];
120+
}
121+
return NULL;
122+
}
123+
85124
/* Return the label if any */
86125
return CommentTab[Addr];
87126
}

0 commit comments

Comments
 (0)