From aa8ac7bbb8d8581ac045c1e9357e99dccba99dde Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Thu, 1 Mar 2012 23:23:05 +1100 Subject: [PATCH] Update to v086r14 release. byuu says: Attempted to fix the bugs pointed out by Cydrak for the shifter carry and subtraction flags. No way to know if I was successful. The memory map should exactly match real hardware now. Also simplified bus reading/writing: we can get fancy when it works, I suppose. Reduced some of the code repetition to try and minimize the chances for bugs. I hopefully fixed up register-based ror shifting to what the docs were saying. And lastly, the disassembler should handle every opcode in every mode now. ldr rn,[pc,n] adds (pc,n) [absolute address] after opcode. I didn't want to actually read from ROM here (in case it ever touches I/O or something), but I suppose we could try anyway. At startup, it will write out "disassembly.txt" which is a disassembly of the entire program ROM. If anyone wants to look for disassembly errors, I'll go ahead and fix them. Just note that I won't do common substitutions like mov pc,lr == ret. At this point, we can make two moves and then the game tells us that we've won. So ... I'm back to thinking the problem is with bugs in the ARM core, and that our bidirectional communication is strong enough to play the game. Although that's not perfect. The game definitely looks at d4 (and possibly others later), but my hardware tests can't get anything but d0/d3 set. --- bsnes/Makefile | 2 +- bsnes/base/base.hpp | 2 +- bsnes/nall/snes/cartridge.hpp | 11 +- bsnes/{clean.bat => purge.bat} | 0 bsnes/snes/chip/armdsp/armdsp.cpp | 21 +++- bsnes/snes/chip/armdsp/armdsp.hpp | 8 +- bsnes/snes/chip/armdsp/disassembler.cpp | 92 ++++++++++++++-- bsnes/snes/chip/armdsp/memory.cpp | 71 ++++-------- bsnes/snes/chip/armdsp/opcodes.cpp | 140 ++++++++++-------------- bsnes/snes/chip/armdsp/registers.hpp | 2 + 10 files changed, 186 insertions(+), 163 deletions(-) rename bsnes/{clean.bat => purge.bat} (100%) diff --git a/bsnes/Makefile b/bsnes/Makefile index dbd165fc..d090f05a 100755 --- a/bsnes/Makefile +++ b/bsnes/Makefile @@ -89,6 +89,6 @@ sync: rm -r phoenix/test archive-all: - tar -cjf bsnes.tar.bz2 base data gameboy libco nall nes obj out phoenix ruby snes ui ui-debugger ui-libsnes Makefile cc.bat clean.bat + tar -cjf bsnes.tar.bz2 base data gameboy libco nall nes obj out phoenix ruby snes ui ui-debugger ui-libsnes Makefile cc.bat purge.bat help:; diff --git a/bsnes/base/base.hpp b/bsnes/base/base.hpp index 9ccfe02a..21285066 100755 --- a/bsnes/base/base.hpp +++ b/bsnes/base/base.hpp @@ -1,7 +1,7 @@ #ifndef BASE_HPP #define BASE_HPP -const char Version[] = "086.13"; +const char Version[] = "086.14"; #include #include diff --git a/bsnes/nall/snes/cartridge.hpp b/bsnes/nall/snes/cartridge.hpp index 0dfbba85..6a350c2c 100755 --- a/bsnes/nall/snes/cartridge.hpp +++ b/bsnes/nall/snes/cartridge.hpp @@ -529,19 +529,10 @@ SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) { if(has_st018) markup.append( " \n" - " \n" - " \n" - " \n" - ); - - #if 0 - if(has_st018) markup.append( - " \n" " \n" " \n" - " \n" + " \n" ); - #endif markup.append("\n"); } diff --git a/bsnes/clean.bat b/bsnes/purge.bat similarity index 100% rename from bsnes/clean.bat rename to bsnes/purge.bat diff --git a/bsnes/snes/chip/armdsp/armdsp.cpp b/bsnes/snes/chip/armdsp/armdsp.cpp index 37f3060f..9fa79e39 100755 --- a/bsnes/snes/chip/armdsp/armdsp.cpp +++ b/bsnes/snes/chip/armdsp/armdsp.cpp @@ -35,13 +35,13 @@ void ArmDSP::enter() { if(pipeline.reload) { pipeline.reload = false; pipeline.prefetch.address = r[15]; - pipeline.prefetch.opcode = bus_read<4>(r[15]); + pipeline.prefetch.opcode = bus_readword(r[15]); r[15].step(); } pipeline.instruction = pipeline.prefetch; pipeline.prefetch.address = r[15]; - pipeline.prefetch.opcode = bus_read<4>(r[15]); + pipeline.prefetch.opcode = bus_readword(r[15]); r[15].step(); //if(pipeline.instruction.address == 0x0000ef5c) trace = 1; @@ -68,11 +68,15 @@ void ArmDSP::enter() { } } +//MMIO: $00-3f|80-bf:3800-38ff +//3800-3807 mirrored throughout +//a0 ignored + uint8 ArmDSP::mmio_read(unsigned addr) { cpu.synchronize_coprocessors(); uint8 data = 0x00; - addr &= 0xffff; + addr &= 0xff06; if(addr == 0x3800) { if(bridge.armtocpu.ready) { @@ -104,7 +108,7 @@ void ArmDSP::mmio_write(unsigned addr, uint8 data) { usleep(200000); } - addr &= 0xffff; + addr &= 0xff06; if(addr == 0x3802) { bridge.cputoarm.ready = true; @@ -131,12 +135,21 @@ void ArmDSP::power() { fp.read(dataROM, 32 * 1024); fp.close(); } + + filename = { dir(filename), "disassembly.txt" }; + fp.open(filename, file::mode::write); + for(unsigned n = 0; n < 128 * 1024; n += 4) { + fp.print(disassemble_opcode(n), "\n"); + } + fp.close(); } void ArmDSP::reset() { create(ArmDSP::Enter, 21477272); for(auto &rd : r) rd = 0; + shiftercarry = 0; + exception = false; pipeline.reload = true; diff --git a/bsnes/snes/chip/armdsp/armdsp.hpp b/bsnes/snes/chip/armdsp/armdsp.hpp index 50fc2e9b..ea9aa712 100755 --- a/bsnes/snes/chip/armdsp/armdsp.hpp +++ b/bsnes/snes/chip/armdsp/armdsp.hpp @@ -42,8 +42,12 @@ struct ArmDSP : public Coprocessor { //memory.cpp uint8 bus_iread(uint32 addr); void bus_iwrite(uint32 addr, uint8 data); - template uint32 bus_read(uint32 addr); - template void bus_write(uint32 addr, uint32 data); + + uint32 bus_readbyte(uint32 addr); + uint32 bus_readword(uint32 addr); + + void bus_writebyte(uint32 addr, uint32 data); + void bus_writeword(uint32 addr, uint32 data); //disassembler.cpp string disassemble_opcode(uint32 pc); diff --git a/bsnes/snes/chip/armdsp/disassembler.cpp b/bsnes/snes/chip/armdsp/disassembler.cpp index 8a7f046b..5366b5b5 100755 --- a/bsnes/snes/chip/armdsp/disassembler.cpp +++ b/bsnes/snes/chip/armdsp/disassembler.cpp @@ -12,10 +12,11 @@ string ArmDSP::disassemble_opcode(uint32 pc) { string output{hex<8>(pc), " "}; - uint32 instruction = bus_read<4>(pc); + uint32 instruction = bus_readword(pc); output.append(hex<8>(instruction), " "); //multiply + //(mul,mla){condition}{s} rd,rm,rs,rn if((instruction & 0x0fc000f0) == 0x00000090) { uint4 condition = instruction >> 28; uint1 accumulate = instruction >> 21; @@ -33,6 +34,7 @@ string ArmDSP::disassemble_opcode(uint32 pc) { } //move to register from status register + //mrs{condition} rd,(c,s)psr if((instruction & 0x0fb000f0) == 0x01000000) { uint4 condition = instruction >> 28; uint1 psr = instruction >> 22; @@ -45,6 +47,7 @@ string ArmDSP::disassemble_opcode(uint32 pc) { } //move to status register from register + //msr{condition} (c,s)psr:{fields},rm if((instruction & 0x0fb000f0) == 0x01200000) { uint4 condition = instruction >> 28; uint1 psr = instruction >> 22; @@ -89,6 +92,34 @@ string ArmDSP::disassemble_opcode(uint32 pc) { return output; } + //data register shift + //{opcode}{condition}{s} rd,rm {shift} rs + //{opcode}{condition} rn,rm {shift} rs + //{opcode}{condition}{s} rd,rn,rm {shift} rs + if((instruction & 0x0e000090) == 0x00000010) { + uint4 condition = instruction >> 28; + uint4 opcode = instruction >> 21; + uint1 save = instruction >> 20; + uint4 rn = instruction >> 16; + uint4 rd = instruction >> 12; + uint4 rs = instruction >> 8; + uint2 mode = instruction >> 5; + uint4 rm = instruction; + + output.append(opcodes[opcode], conditions[condition]); + if(is_move(opcode)) output.append(save ? "s " : " ", registers[rd], ","); + if(is_comp(opcode)) output.append(registers[rn], ","); + if(is_math(opcode)) output.append(save ? "s " : " ", registers[rd], ",", registers[rn], ","); + output.append(registers[rm]); + if(mode == 0) output.append(" lsl "); + if(mode == 1) output.append(" lsr "); + if(mode == 2) output.append(" asr "); + if(mode == 3) output.append(" ror "); + output.append(registers[rs]); + + return output; + } + //data immediate //{opcode}{condition}{s} rd,#immediate //{opcode}{condition} rn,#immediate @@ -113,21 +144,58 @@ string ArmDSP::disassemble_opcode(uint32 pc) { } //move immediate offset - //(ldr,str){condition}{b} rd,[rn{+offset}] - //todo: support W flag + //(ldr,str){condition}{b} rd,[rn{,+/-offset}]{!} + //(ldr,str){condition}{b} rd,[rn]{,+/-offset} if((instruction & 0x0e000000) == 0x04000000) { uint4 condition = instruction >> 28; + uint1 p = instruction >> 24; uint1 u = instruction >> 23; + uint1 b = instruction >> 22; + uint1 w = instruction >> 21; uint1 load = instruction >> 20; uint4 rn = instruction >> 16; uint4 rd = instruction >> 12; uint12 immediate = instruction; - output.append(load ? "ldr" : "str", conditions[condition]); - if(instruction & 0x00400000) output.append("b"); - output.append(" ", registers[rd], ",[", registers[rn]); - if(immediate) output.append(u ? "+" : "-", "0x", hex<3>((uint12)instruction)); - output.append("]"); + output.append(load ? "ldr" : "str", conditions[condition], b ? "b " : " "); + output.append(registers[rd], ",[", registers[rn]); + if(p == 0) output.append("]"); + if(immediate) output.append(",", u ? "+" : "-", "0x", hex<3>(immediate)); + if(p == 1) output.append("]"); + if(p == 1 && w == 1) output.append("!"); + + if(rn == 15) output.append(" (0x", hex<8>(pc + 8 + (u ? +immediate : -immediate)), ")"); + + return output; + } + + //move register offset + //(ldr)(str){condition}{b} rd,[rn,rm {mode} #immediate]{!} + //(ldr)(str){condition}{b} rd,[rn],rm {mode} #immediate + if((instruction & 0x0e000010) == 0x06000000) { + uint4 condition = instruction >> 28; + uint1 p = instruction >> 24; + uint1 u = instruction >> 23; + uint1 b = instruction >> 22; + uint1 w = instruction >> 21; + uint1 load = instruction >> 20; + uint4 rn = instruction >> 16; + uint4 rd = instruction >> 12; + uint5 shift = instruction >> 7; + uint2 mode = instruction >> 5; + uint4 rm = instruction; + + output.append(load ? "ldr" : "str", conditions[condition], b ? "b " : " "); + output.append(registers[rd], ",[", registers[rn]); + if(p == 0) output.append("]"); + output.append(",", u ? "+" : "-", registers[rm]); + if(mode == 0 && shift != 0) output.append(" lsl #", shift); + if(mode == 1) output.append(" lsr #", shift == 0 ? 32u : (unsigned)shift); + if(mode == 2) output.append(" asr #", shift == 0 ? 32u : (unsigned)shift); + if(mode == 3 && shift != 0) output.append(" ror #", shift); + if(mode == 3 && shift == 0) output.append(" rrx"); + if(p == 1) output.append("]"); + if(p == 1 && w == 1) output.append("!"); return output; } @@ -166,10 +234,12 @@ string ArmDSP::disassemble_opcode(uint32 pc) { string ArmDSP::disassemble_registers() { return { "r0:", hex<8>(r[ 0]), " r1:", hex<8>(r[ 1]), " r2:", hex<8>(r[ 2]), " r3:", hex<8>(r[ 3]), - " r4:", hex<8>(r[ 4]), " r5:", hex<8>(r[ 5]), " r6:", hex<8>(r[ 6]), " r7:", hex<8>(r[ 7]), "\n", + " r4:", hex<8>(r[ 4]), " r5:", hex<8>(r[ 5]), " r6:", hex<8>(r[ 6]), " r7:", hex<8>(r[ 7]), " ", + "cpsr:", cpsr.n ? "N" : "n", cpsr.z ? "Z" : "z", cpsr.c ? "C" : "c", cpsr.v ? "V" : "v", "\n", "r8:", hex<8>(r[ 8]), " r9:", hex<8>(r[ 9]), " r10:", hex<8>(r[10]), " r11:", hex<8>(r[11]), - " r12:", hex<8>(r[12]), " r13:", hex<8>(r[13]), " r14:", hex<8>(r[14]), " r15:", hex<8>(r[15]), "\n", - "cpsr:", cpsr.n ? "N" : "n", cpsr.z ? "Z" : "z", cpsr.c ? "C" : "c", cpsr.v ? "V" : "v" + " r12:", hex<8>(r[12]), " r13:", hex<8>(r[13]), " r14:", hex<8>(r[14]), " r15:", hex<8>(r[15]), " ", + "spsr:", spsr.n ? "N" : "n", spsr.z ? "Z" : "z", spsr.c ? "C" : "c", spsr.v ? "V" : "v" + }; } diff --git a/bsnes/snes/chip/armdsp/memory.cpp b/bsnes/snes/chip/armdsp/memory.cpp index 3eab5ddd..9bf9c321 100755 --- a/bsnes/snes/chip/armdsp/memory.cpp +++ b/bsnes/snes/chip/armdsp/memory.cpp @@ -58,61 +58,30 @@ void ArmDSP::bus_iwrite(uint32 addr, uint8 data) { if((addr & 3) == 0) print("* ARM w", hex<8>(addr), " = ", hex<2>(data), "\n"); } -template -uint32 ArmDSP::bus_read(uint32 addr) { - uint32 data = 0; - - if(size == 1) { - uint32 mask = 255u << ((addr & ~3) << 3); - data |= bus_iread(addr) & mask; - } - - if(size == 4) { - addr &= ~3; - data |= bus_iread(addr + 0) << 0; - data |= bus_iread(addr + 1) << 8; - data |= bus_iread(addr + 2) << 16; - data |= bus_iread(addr + 3) << 24; - } - - if(0&&addr >= 0x40000000 && addr <= 0x400000ff) { - if(addr != 0x40000020 || data != 0x80) - if(data) { - if(size == 1) print("* ARM r", hex<8>(addr), " = ", hex<2>(data), "\n"); - if(size == 2) print("* ARM r", hex<8>(addr), " = ", hex<4>(data), "\n"); - if(size == 4) print("* ARM r", hex<8>(addr), " = ", hex<8>(data), "\n"); - usleep(20000); - } - } - - if(size == 1) return data & 0xff; - if(size == 2) return data & 0xffff; - return data; +uint32 ArmDSP::bus_readbyte(uint32 addr) { + return bus_iread(addr); } -template -void ArmDSP::bus_write(uint32 addr, uint32 data) { - if(0&&addr >= 0x40000000 && addr <= 0x400000ff) { - if(data) { - if(size == 1) print("* ARM w", hex<8>(addr), " = ", hex<2>(data), "\n"); - if(size == 2) print("* ARM w", hex<8>(addr), " = ", hex<4>(data), "\n"); - if(size == 4) print("* ARM w", hex<8>(addr), " = ", hex<8>(data), "\n"); - usleep(20000); - } - } +uint32 ArmDSP::bus_readword(uint32 addr) { + addr &= ~3; + return ( + (bus_iread(addr + 0) << 0) + | (bus_iread(addr + 1) << 8) + | (bus_iread(addr + 2) << 16) + | (bus_iread(addr + 3) << 24) + ); +} - if(size == 1) { - uint32 mask = 255u << ((addr & ~3) << 3); - bus_iwrite(addr, data); - } +void ArmDSP::bus_writebyte(uint32 addr, uint32 data) { + return bus_iwrite(addr, data); +} - if(size == 4) { - addr &= ~3; - bus_iwrite(addr + 0, data >> 0); - bus_iwrite(addr + 1, data >> 8); - bus_iwrite(addr + 2, data >> 16); - bus_iwrite(addr + 3, data >> 24); - } +void ArmDSP::bus_writeword(uint32 addr, uint32 data) { + addr &= ~3; + bus_iwrite(addr + 0, data >> 0); + bus_iwrite(addr + 1, data >> 8); + bus_iwrite(addr + 2, data >> 16); + bus_iwrite(addr + 3, data >> 24); } #endif diff --git a/bsnes/snes/chip/armdsp/opcodes.cpp b/bsnes/snes/chip/armdsp/opcodes.cpp index 3fda67b6..b6425fa4 100755 --- a/bsnes/snes/chip/armdsp/opcodes.cpp +++ b/bsnes/snes/chip/armdsp/opcodes.cpp @@ -29,56 +29,53 @@ bool ArmDSP::condition() { //ro = modified target void ArmDSP::opcode(uint32 rm) { uint4 opcode = instruction >> 21; - uint1 s = instruction >> 20; + uint1 save = instruction >> 20; uint4 n = instruction >> 16; uint4 d = instruction >> 12; uint32 rn = r[n]; - auto &rd = r[d]; - uint32 ri = rd, ro; - //comparison opcodes always update flags - if(opcode >= 8 && opcode <= 11) assert(s == 1); + //comparison opcodes always update flags (debug test) + //this can be removed later: s=0 opcode=8-11 is invalid + if(opcode >= 8 && opcode <= 11) assert(save == 1); - auto bit = [&](uint32 ro) { - if(!s) return; - cpsr.n = ro >> 31; - cpsr.z = ro == 0; + auto test = [&](uint32 result) { + if(save) { + cpsr.n = result >> 31; + cpsr.z = result == 0; + cpsr.c = shiftercarry; + } + return result; }; - auto add = [&](uint32 ro) { - if(!s) return; - cpsr.n = ro >> 31; - cpsr.z = ro == 0; - cpsr.c = ro < ri; - cpsr.v = ~(ri ^ rm) & (ri ^ ro) & (1u << 31); - }; - - auto sub = [&](uint32 ro) { - if(!s) return; - cpsr.n = ro >> 31; - cpsr.z = ro == 0; - cpsr.c = ro > ri; - cpsr.v = (ri ^ rm) & (ri ^ ro) & (1u << 31); + auto math = [&](uint32 source, uint32 modify, bool carry) { + uint32 result = source + modify + carry; + if(save) { + cpsr.n = result >> 31; + cpsr.z = result == 0; + cpsr.c = result < source; + cpsr.v = ~(source ^ modify) & (source ^ result) & (1u << 31); + } + return result; }; switch(opcode) { - case 0: rd = rn & rm; bit(rd); break; //AND (logical and) - case 1: rd = rn ^ rm; bit(rd); break; //EOR (logical exclusive or) - case 2: rd = rn - rm; sub(rd); break; //SUB (subtract) - case 3: rd = rm - rn; sub(rd); break; //RSB (reverse subtract) - case 4: rd = rn + rm; add(rd); break; //ADD (add) - case 5: rd = rn + rm + cpsr.c; add(rd); break; //ADC (add with carry) - case 6: rd = rn - rm -!cpsr.c; sub(rd); break; //SBC (subtract with carry) - case 7: rd = rm - rn -!cpsr.c; sub(rd); break; //RSC (reverse subtract with carry) - case 8: ro = rn & rm; bit(ro); break; //TST (test) - case 9: ro = rn ^ rm; bit(ro); break; //TEQ (test equivalence) - case 10: ro = rn - rm; sub(ro); break; //CMP (compare) - case 11: ro = rn + rm; add(ro); break; //CMN (compare negated) - case 12: rd = rn | rm; bit(rd); break; //ORR (logical inclusive or) - case 13: rd = rm; bit(rd); break; //MOV (move) - case 14: rd = rn &~rm; bit(rd); break; //BIC (bit clear) - case 15: rd =~rm; bit(rd); break; //MVN (move not) + case 0: r[d] = test(rn & rm); break; //AND + case 1: r[d] = test(rn ^ rm); break; //EOR + case 2: r[d] = math(rn, ~rm, 1); break; //SUB + case 3: r[d] = math(rm, ~rn, 1); break; //RSB + case 4: r[d] = math(rn, rm, 0); break; //ADD + case 5: r[d] = math(rn, rm, cpsr.c); break; //ADC + case 6: r[d] = math(rn, ~rm, cpsr.c); break; //SBC + case 7: r[d] = math(rm, ~rn, cpsr.c); break; //RSC + case 8: test(rn & rm); break; //TST + case 9: test(rn ^ rm); break; //TEQ + case 10: math(rn, ~rm, 1); break; //CMP + case 11: math(rn, rm, 0); break; //CMN + case 12: r[d] = test(rn | rm); break; //ORR + case 13: r[d] = test(rm); break; //MOV + case 14: r[d] = test(rn &~rm); break; //BIC + case 15: r[d] = test(~rm); break; //MVN } } @@ -203,7 +200,7 @@ void ArmDSP::op_data_immediate_shift() { if(mode == 2) asr(c, rm, rs ? rs : 32); if(mode == 3) rs ? ror(c, rm, rs) : rrx(c, rm); - if(save) cpsr.c = c; + shiftercarry = c; opcode(rm); } @@ -232,9 +229,9 @@ void ArmDSP::op_data_register_shift() { if(mode == 0) lsl(c, rm, rs < 33 ? rs : 33); if(mode == 1) lsr(c, rm, rs < 33 ? rs : 33); if(mode == 2) asr(c, rm, rs < 32 ? rs : 32); - if(mode == 3) ror(c, rm, rs < 32 ? rs : 32); + if(mode == 3 && rs) ror(c, rm, rs & 31 == 0 ? 32 : rs & 31); - if(save) cpsr.c = c; + shiftercarry = c; opcode(rm); } @@ -254,17 +251,15 @@ void ArmDSP::op_data_immediate() { uint4 shift = instruction >> 8; uint8 immediate = instruction; - bool c = cpsr.c; - uint32 rs = shift << 1; uint32 rm = (immediate >> rs) | (immediate << (32 - rs)); - if(rs) c = immediate >> 31; + if(rs) shiftercarry = immediate >> 31; - if(save) cpsr.c = c; opcode(rm); } -//(ldr,str){condition}{b} rd,[rn{+offset}] +//(ldr,str){condition}{b} rd,[rn{,+/-offset}]{!} +//(ldr,str){condition}{b} rd,[rn]{,+/-offset} //cccc 010p ubwl nnnn dddd iiii iiii iiii //c = condition //p = pre (0 = post-indexed addressing) @@ -288,22 +283,16 @@ void ArmDSP::op_move_immediate_offset() { uint32 rn = r[n]; auto &rd = r[d]; - if(l) { - if(p == 1) rn = u ? rn + rm : rn - rm; - if(b) rd = bus_read<1>(rn); - else rd = bus_read<4>(rn); - if(p == 0) rn = u ? rn + rm : rn - rm; - } else { - if(p == 1) rn = u ? rn + rm : rn - rm; - if(b) bus_write<1>(rn, rd); - else bus_write<4>(rn, rd); - if(p == 0) rn = u ? rn + rm : rn - rm; - } + if(p == 1) rn = u ? rn + rm : rn - rm; + if(l) rd = b ? bus_readbyte(rn) : bus_readword(rn); + else b ? bus_writebyte(rn, rd) : bus_writeword(rn, rd); + if(p == 0) rn = u ? rn + rm : rn - rm; if(p == 0 || w == 1) r[n] = rn; } -//(ldr)(str){condition}{b} rd,rn,rm {mode} #immediate +//(ldr)(str){condition}{b} rd,[rn,rm {mode} #immediate]{!} +//(ldr)(str){condition}{b} rd,[rn],rm {mode} #immediate //cccc 011p ubwl nnnn dddd llll lss0 mmmm //c = condition //p = pre (0 = post-indexed addressing) @@ -339,17 +328,10 @@ void ArmDSP::op_move_register_offset() { if(mode == 2) asr(c, rm, rs ? rs : 32); if(mode == 3) rs ? ror(c, rm, rs) : rrx(c, rm); - if(l) { - if(p == 1) rn = u ? rn + rm : rn - rm; - if(b) rd = bus_read<1>(rn); - else rd = bus_read<4>(rn); - if(p == 0) rn = u ? rn + rm : rn - rm; - } else { - if(p == 1) rn = u ? rn + rm : rn - rm; - if(b) bus_write<1>(rn, rd); - else bus_write<4>(rn, rd); - if(p == 0) rn = u ? rn + rm : rn - rm; - } + if(p == 1) rn = u ? rn + rm : rn - rm; + if(l) rd = b ? bus_readbyte(rn) : bus_readword(rn); + else b ? bus_writebyte(rn, rd) : bus_writeword(rn, rd); + if(p == 0) rn = u ? rn + rm : rn - rm; if(p == 0 || w == 1) r[n] = rn; } @@ -379,19 +361,11 @@ void ArmDSP::op_move_multiple() { if(p == 1 && u == 0) rn = rn - bit::count(list) * 4 + 0; //DB if(p == 0 && u == 0) rn = rn - bit::count(list) * 4 + 4; //DA - if(l) { - for(unsigned n = 0; n < 16; n++) { - if(list & (1 << n)) { - r[n] = bus_read<4>(rn); - rn += 4; - } - } - } else { - for(unsigned n = 0; n < 16; n++) { - if(list & (1 << n)) { - bus_write<4>(rn, r[n]); - rn += 4; - } + for(unsigned n = 0; n < 16; n++) { + if(list & (1 << n)) { + if(l) r[n] = bus_readword(rn); + else bus_writeword(rn, r[n]); + rn += 4; } } diff --git a/bsnes/snes/chip/armdsp/registers.hpp b/bsnes/snes/chip/armdsp/registers.hpp index 6f3d28ba..e46461f0 100755 --- a/bsnes/snes/chip/armdsp/registers.hpp +++ b/bsnes/snes/chip/armdsp/registers.hpp @@ -101,6 +101,8 @@ struct Register { } } r[16]; +bool shiftercarry; + struct Pipeline { bool reload; struct Instruction {