Start on 65816

This commit is contained in:
Lauri Kasanen 2022-10-12 11:03:57 +03:00
parent eede412959
commit 67384a29b7
7 changed files with 156 additions and 14 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

@ -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

@ -121,8 +121,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;
}
@ -322,14 +324,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 +374,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 +567,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 +598,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));
}

View File

@ -427,8 +427,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:

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;

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;};"
}