mirror of
https://github.com/cc65/cc65.git
synced 2024-12-27 00:29:31 +00:00
Start on 65816
This commit is contained in:
parent
eede412959
commit
67384a29b7
@ -115,14 +115,14 @@ Here is a description of all the command line options:
|
|||||||
<item>6502dtv
|
<item>6502dtv
|
||||||
<item>65sc02
|
<item>65sc02
|
||||||
<item>65c02
|
<item>65c02
|
||||||
|
<item>65816
|
||||||
<item>huc6280
|
<item>huc6280
|
||||||
<item>4510
|
<item>4510
|
||||||
</itemize>
|
</itemize>
|
||||||
|
|
||||||
6502x is for the NMOS 6502 with unofficial opcodes. 6502dtv is for the
|
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.
|
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
|
4510 is the CPU of the Commodore C65. 65816 is the CPU of the SNES.
|
||||||
is not available.
|
|
||||||
|
|
||||||
|
|
||||||
<label id="option--formfeeds">
|
<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
|
branches point outside of the disassembled memory. This can happen when text
|
||||||
or binary data is processed.
|
or binary data is processed.
|
||||||
|
|
||||||
While there is some code for the 65816 in the sources, it is currently
|
The 65816 support requires annotating ranges with the M and X flag states.
|
||||||
unsupported.
|
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>
|
<sect1>Attribute map<p>
|
||||||
@ -521,6 +522,11 @@ following attributes are recognized:
|
|||||||
|
|
||||||
</descrip>
|
</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>
|
</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>
|
<sect>Copyright<p>
|
||||||
|
|
||||||
da65 (and all cc65 binutils) is (C) Copyright 1998-2011, Ullrich von
|
da65 (and all cc65 binutils) is (C) Copyright 1998-2011, Ullrich von
|
||||||
|
@ -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)
|
unsigned GetRemainingBytes (void)
|
||||||
/* Return the number of remaining code bytes */
|
/* Return the number of remaining code bytes */
|
||||||
{
|
{
|
||||||
|
@ -72,6 +72,9 @@ unsigned GetCodeWord (unsigned Addr);
|
|||||||
unsigned long GetCodeDWord (unsigned Addr);
|
unsigned long GetCodeDWord (unsigned Addr);
|
||||||
/* Get a dword from the given address */
|
/* Get a dword from the given address */
|
||||||
|
|
||||||
|
unsigned GetCodeLongAddr (unsigned Addr);
|
||||||
|
/* Get a 24-bit address from the given address */
|
||||||
|
|
||||||
unsigned GetRemainingBytes (void);
|
unsigned GetRemainingBytes (void);
|
||||||
/* Return the number of remaining code bytes */
|
/* Return the number of remaining code bytes */
|
||||||
|
|
||||||
|
@ -121,8 +121,10 @@ static const char* GetAddrArg (unsigned Flags, unsigned Addr)
|
|||||||
static char Buf [32];
|
static char Buf [32];
|
||||||
if (Addr < 0x100) {
|
if (Addr < 0x100) {
|
||||||
xsprintf (Buf, sizeof (Buf), "$%02X", Addr);
|
xsprintf (Buf, sizeof (Buf), "$%02X", Addr);
|
||||||
} else {
|
} else if (Addr < 0x10000) {
|
||||||
xsprintf (Buf, sizeof (Buf), "$%04X", Addr);
|
xsprintf (Buf, sizeof (Buf), "$%04X", Addr);
|
||||||
|
} else {
|
||||||
|
xsprintf (Buf, sizeof (Buf), "$%06X", Addr);
|
||||||
}
|
}
|
||||||
return Buf;
|
return Buf;
|
||||||
}
|
}
|
||||||
@ -322,14 +324,28 @@ void OH_AbsoluteY (const OpcDesc* D)
|
|||||||
|
|
||||||
void OH_AbsoluteLong (const OpcDesc* D attribute ((unused)))
|
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)))
|
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 +374,17 @@ void OH_Relative (const OpcDesc* D)
|
|||||||
|
|
||||||
void OH_RelativeLong (const OpcDesc* D attribute ((unused)))
|
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 +567,15 @@ void OH_ImmediateAbsoluteX (const OpcDesc* D)
|
|||||||
|
|
||||||
void OH_StackRelative (const OpcDesc* D attribute ((unused)))
|
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)))
|
void OH_DirectIndirectLongX (const OpcDesc* D attribute ((unused)))
|
||||||
{
|
{
|
||||||
Error ("Not implemented");
|
Error ("Not implemented %s", __FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -571,14 +598,28 @@ void OH_StackRelativeIndirectY4510 (const OpcDesc* D attribute ((unused)))
|
|||||||
|
|
||||||
void OH_DirectIndirectLong (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)))
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -427,8 +427,13 @@ static void OneOpcode (unsigned RemainingBytes)
|
|||||||
switch (Style) {
|
switch (Style) {
|
||||||
|
|
||||||
case atDefault:
|
case atDefault:
|
||||||
D->Handler (D);
|
if (CPU == CPU_65816) {
|
||||||
PC += D->Size;
|
DataByteLine (1);
|
||||||
|
++PC;
|
||||||
|
} else {
|
||||||
|
D->Handler (D);
|
||||||
|
PC += D->Size;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case atCode:
|
case atCode:
|
||||||
|
@ -74,6 +74,7 @@ void SetOpcTable (cpu_t CPU)
|
|||||||
case CPU_6502DTV: OpcTable = OpcTable_6502DTV; break;
|
case CPU_6502DTV: OpcTable = OpcTable_6502DTV; break;
|
||||||
case CPU_65SC02: OpcTable = OpcTable_65SC02; break;
|
case CPU_65SC02: OpcTable = OpcTable_65SC02; break;
|
||||||
case CPU_65C02: OpcTable = OpcTable_65C02; break;
|
case CPU_65C02: OpcTable = OpcTable_65C02; break;
|
||||||
|
case CPU_65816: OpcTable = OpcTable_65816; break;
|
||||||
case CPU_HUC6280: OpcTable = OpcTable_HuC6280; break;
|
case CPU_HUC6280: OpcTable = OpcTable_HuC6280; break;
|
||||||
case CPU_M740: OpcTable = OpcTable_M740; break;
|
case CPU_M740: OpcTable = OpcTable_M740; break;
|
||||||
case CPU_4510: OpcTable = OpcTable_4510; break;
|
case CPU_4510: OpcTable = OpcTable_4510; break;
|
||||||
|
61
util/parse-bsnes-log.awk
Executable file
61
util/parse-bsnes-log.awk
Executable 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;};"
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user