1
0
mirror of https://github.com/ksherlock/x65.git synced 2024-06-01 12:41:28 +00:00

Bug fixes

- rtl instruction had wrong opcode
- disassembler works a lot better with correct rtl, even for 6502
- disassembler can specify n bytes of data before code starts in src
mode (data=initial data size)
This commit is contained in:
Carl-Henrik Skårstedt 2015-11-27 18:01:53 -08:00
parent bdc013350c
commit 65f19b4a47
2 changed files with 46 additions and 20 deletions

View File

@ -786,7 +786,7 @@ struct dismnm a65816_ops[256] = {
{ "rtl", AM_NON, 0x00 },
{ "adc", AM_IMM_DBL_A, 0x01 },
{ "ror", AM_NON, 0x00 },
{ "???", AM_NON, 0x00 },
{ "rtl", AM_NON, 0x00 },
{ "jmp", AM_REL, 0x02 },
{ "adc", AM_ABS, 0x02 },
{ "ror", AM_ABS, 0x02 },
@ -967,20 +967,31 @@ std::vector<RefAddr> refs;
static int _sortRefs(const void *A, const void *B)
{
return ((const RefLink*)A)->instr_addr - ((const RefLink*)B)->instr_addr;
return ((const RefAddr*)A)->address - ((const RefAddr*)B)->address;
}
void GetReferences(unsigned char *mem, size_t bytes, bool acc_16, bool ind_16, int addr, const dismnm *opcodes)
void GetReferences(unsigned char *mem, size_t bytes, bool acc_16, bool ind_16, int addr, const dismnm *opcodes, int init_data)
{
int start_addr = addr;
int end_addr = addr + (int)bytes;
refs.push_back(RefAddr(start_addr));
refs[0].pRefs = new std::vector<RefLink>();
if (init_data) {
refs[0].data = 1;
refs.push_back(RefAddr(start_addr+init_data));
refs[1].pRefs = new std::vector<RefLink>();
}
unsigned char *mem_orig = mem;
size_t bytes_orig = bytes;
int addr_orig = addr;
if (size_t(init_data)>bytes)
return;
addr += init_data;
bytes -= init_data;
while (bytes) {
unsigned char op = *mem++;
int curr = addr;
@ -1060,13 +1071,15 @@ void GetReferences(unsigned char *mem, size_t bytes, bool acc_16, bool ind_16, i
mem = mem_orig;
bytes = bytes_orig;
addr = addr_orig;
int curr_label = 0;
int curr_label = init_data ? 1 : 0;
int prev_addr = -1;
bool was_data = false;
bool was_data = init_data>0;
refs[curr_label].data = 0;
bool separator = false;
int prev_op = 0xff;
while (bytes && curr_label<refs.size()) {
addr += init_data;
bytes -= init_data;
while (bytes && curr_label<(int)refs.size()) {
unsigned char op = *mem++;
int curr = addr;
bytes--;
@ -1091,7 +1104,7 @@ void GetReferences(unsigned char *mem, size_t bytes, bool acc_16, bool ind_16, i
arg_size = ind_16 ? 2 : 1;
break;
}
if (arg_size > bytes)
if (arg_size > (int)bytes)
break; // ended on partial instruction
addr += arg_size;
bytes -= arg_size;
@ -1151,7 +1164,7 @@ void GetReferences(unsigned char *mem, size_t bytes, bool acc_16, bool ind_16, i
// after a separator if there is no jmp, jsr, brl begin data block
if (!was_data) {
if (op == 0x60 || op == 0x40 || op == 0x68 || op == 0x4c || op == 0x6c ||
if (op == 0x60 || op == 0x40 || op == 0x6b || op == 0x4c || op == 0x6c ||
op == 0x7c || op == 0x5c || op == 0xdc) { // rts, rti, rtl or jmp
separator = true;
for (size_t i = curr_label+1; i<refs.size() && (refs[i].address-curr)<0x7e; i++) { // check no branch crossing
@ -1192,8 +1205,11 @@ void GetReferences(unsigned char *mem, size_t bytes, bool acc_16, bool ind_16, i
}
std::vector<RefAddr>::iterator k = refs.begin();
if (k != refs.end())
if (k != refs.end()) {
++k; // don't delete the initial label
if (init_data && k != refs.end())
++k; // don't delete the initial label
}
while (k!=refs.end()) {
if (k->pRefs && k->pRefs->size()==0) {
delete k->pRefs;
@ -1204,7 +1220,7 @@ void GetReferences(unsigned char *mem, size_t bytes, bool acc_16, bool ind_16, i
}
static const char spacing[] = " ";
void Disassemble(strref filename, unsigned char *mem, size_t bytes, bool acc_16, bool ind_16, int addr, const dismnm *opcodes, bool src)
void Disassemble(strref filename, unsigned char *mem, size_t bytes, bool acc_16, bool ind_16, int addr, const dismnm *opcodes, bool src, int init_data)
{
FILE *f = stdout;
bool opened = false;
@ -1223,17 +1239,17 @@ void Disassemble(strref filename, unsigned char *mem, size_t bytes, bool acc_16,
int end_addr = addr + (int)bytes;
refs.clear();
GetReferences(mem, bytes, acc_16, ind_16, addr, opcodes);
GetReferences(mem, bytes, acc_16, ind_16, addr, opcodes, init_data);
int curr_label_index = 0;
bool separator = false;
bool is_data = false;
bool is_data = refs.size() ? !!refs[0].data : false;
strown<256> out;
int prev_op = 255;
while (bytes) {
bool data_to_code = false;
// Determine if current address is referenced from somewhere
while (curr_label_index<refs.size() && addr >= refs[curr_label_index].address) {
while (curr_label_index<(int)refs.size() && addr >= refs[curr_label_index].address) {
struct RefAddr &ref = refs[curr_label_index];
if (ref.pRefs) {
for (size_t j = 0; j<ref.pRefs->size(); ++j) {
@ -1334,7 +1350,7 @@ void Disassemble(strref filename, unsigned char *mem, size_t bytes, bool acc_16,
int reference = -1;
separator = false;
if (op == 0x60 || op == 0x40 || op == 0x68 || (op == 0x4c && mem[arg_size] != 0x4c) ||
if (op == 0x60 || op == 0x40 || op == 0x6b || (op == 0x4c && mem[arg_size] != 0x4c) ||
op == 0x6c || op == 0x7c || op == 0x5c || op == 0xdc) { // rts, rti, rtl or jmp
separator = true;
for (size_t i = 0; i<refs.size(); i++) {
@ -1441,14 +1457,16 @@ void Disassemble(strref filename, unsigned char *mem, size_t bytes, bool acc_16,
if (!src && lblname)
out.sprintf_append(" ; %s", lblname.c_str());
else if (src && lblname)
out.sprintf_append(" ; $%4x", reference);
out.sprintf_append(" ; $%04x", reference);
mem += arg_size;
out.append('\n');
fputs(out.c_str(), f);
prev_op = op;
}
if (separator || ((curr_label_index)<refs.size() && refs[curr_label_index].address==addr && is_data && !refs[curr_label_index].data)) {
if (separator || (curr_label_index<(int)refs.size() &&
refs[curr_label_index].address==addr && is_data &&
!refs[curr_label_index].data)) {
fputs("\n", f);
fputs(spc, f);
fprintf(f, "; ------------- $%04x ------------- ;\n\n", addr);
@ -1473,6 +1491,7 @@ int main(int argc, char **argv)
int skip = 0;
int end = 0;
int addr = 0x1000;
int data = 0;
bool acc_16 = true;
bool ind_16 = true;
bool src = false;
@ -1512,6 +1531,12 @@ int main(int argc, char **argv)
if (arg.get_first() == '$')
++arg;
addr = arg.ahextoui();
} else if (var.same_str("data")) {
if (arg.get_first() == '$') {
++arg;
data = arg.ahextoui();
} else
data = arg.atoi();
} else if (var.same_str("cpu")) {
if (arg.same_str("65816"))
opcodes = a65816_ops;
@ -1544,7 +1569,7 @@ int main(int argc, char **argv)
size_t bytes = size - skip;
if (end && bytes > size_t(end - skip))
bytes = size_t(end - skip);
Disassemble(out, mem + skip, bytes, acc_16, ind_16, addr, opcodes, src);
Disassemble(out, mem + skip, bytes, acc_16, ind_16, addr, opcodes, src, data);
}
free(mem);
}

View File

@ -663,7 +663,7 @@ struct mnem opcodes_65816[] = {
{ "jsl", AM8_JSL, { 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ "rti", AMM_NON, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ "rts", AMM_NON, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ "rtl", AMM_NON, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ "rtl", AMM_NON, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
{ "ora", AM8_ORA, { 0x01, 0x05, 0x09, 0x0d, 0x11, 0x15, 0x19, 0x1d, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x07, 0x17, 0x0f, 0x1f, 0x03, 0x13, 0x00, 0x00 } },
{ "and", AM8_ORA, { 0x21, 0x25, 0x29, 0x2d, 0x31, 0x35, 0x39, 0x3d, 0x00, 0x00, 0x00, 0x32, 0x00, 0x00, 0x27, 0x37, 0x2f, 0x3f, 0x23, 0x33, 0x00, 0x00 } },
{ "eor", AM8_ORA, { 0x41, 0x45, 0x49, 0x4d, 0x51, 0x55, 0x59, 0x5d, 0x00, 0x00, 0x00, 0x52, 0x00, 0x00, 0x47, 0x57, 0x4f, 0x5f, 0x43, 0x53, 0x00, 0x00 } },
@ -5253,7 +5253,7 @@ StatusCode Asm::GetAddressMode(strref line, bool flipXY, unsigned int validModes
if (!c)
addrMode = AMB_NON;
else if (!force_abs && (c == '[' || (c == '(' &&
(validModes&(AMM_REL | AMM_REL_X | AMM_ZP_REL_X | AMM_ZP_Y_REL))))) {
(validModes&(AMM_REL | AMM_REL_X | AMM_ZP_REL | AMM_ZP_REL_X | AMM_ZP_Y_REL))))) {
deco = line.scoped_block_skip();
line.skip_whitespace();
expression = deco.split_token_trim(',');
@ -5520,7 +5520,7 @@ StatusCode Asm::AddOpcode(strref line, int index, strref source_file)
AddTriple(value);
break;
case CA_TWO_ARG_BYTES: {
case CA_TWO_ARG_BYTES: {
if (evalLater)
AddLateEval(CurrSection().DataOffset(), CurrSection().GetPC(), scope_address[scope_depth], expression, source_file, LateEval::LET_BYTE);
else if (error == STATUS_RELATIVE_SECTION) {
@ -5613,6 +5613,7 @@ StatusCode Asm::BuildLine(strref line)
strref line_start = line;
char char0 = line[0]; // first char including white space
line.skip_whitespace(); // skip to first character
line = line.before_or_full(';'); // clip any line comments
line = line.before_or_full(c_comment);
line.clip_trailing_whitespace();