From ad71e18e02c7ce5fcbf2d60eedd46bc449c084bb Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Wed, 29 Feb 2012 23:59:48 +1100 Subject: [PATCH] Update to v086r13 release. byuu says: That's my best implementation of the shifter carry. It's horribly inefficient and possibly wrong (especially on ROR by register, but that doesn't ever appear to be used in this program), but oh well. It's the best I can do. Game is basically getting stuck after a board upload and issuing another command. It's sitting in a loop waiting on $3804.d0 to be set, meaning the ARM is never writing anything for the CPU to read. There's some chance that my $3804/r40000000 flags are wrong. Short of guessing though, I'm not sure how we can get more info on how those work. ... I really can't debug this any better than I have. If no one else sees anything, then we're going to have to give up and wait for MESS to create opcode logs for us to compare against. --- bsnes/base/base.hpp | 3 +- bsnes/nall/bit.hpp | 38 +++-- bsnes/nall/platform.hpp | 2 +- bsnes/nall/varint.hpp | 82 ++++++----- bsnes/nes/video/video.cpp | 7 +- bsnes/snes/chip/armdsp/armdsp.cpp | 3 +- bsnes/snes/chip/armdsp/armdsp.hpp | 7 +- bsnes/snes/chip/armdsp/disassembler.cpp | 29 +++- bsnes/snes/chip/armdsp/opcodes.cpp | 185 +++++++++++------------- bsnes/snes/chip/armdsp/registers.hpp | 2 +- bsnes/snes/chip/msu1/msu1.cpp | 6 +- 11 files changed, 198 insertions(+), 166 deletions(-) diff --git a/bsnes/base/base.hpp b/bsnes/base/base.hpp index 0088df18..9ccfe02a 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.12"; +const char Version[] = "086.13"; #include #include @@ -121,6 +121,7 @@ typedef uint29_t uint29; typedef uint30_t uint30; typedef uint31_t uint31; typedef uint32_t uint32; +typedef uint_t<33> uint33; typedef uint64_t uint64; typedef varuint_t varuint; diff --git a/bsnes/nall/bit.hpp b/bsnes/nall/bit.hpp index d5e5e1bd..2732efce 100755 --- a/bsnes/nall/bit.hpp +++ b/bsnes/nall/bit.hpp @@ -1,45 +1,56 @@ #ifndef NALL_BIT_HPP #define NALL_BIT_HPP +#include + namespace nall { - template constexpr inline unsigned uclamp(const unsigned x) { - enum { y = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1) }; + template + constexpr inline type_t uclamp(const type_t x) { + enum : type_t { b = 1ull << (bits - 1), y = b * 2 - 1 }; return y + ((x - y) & -(x < y)); //min(x, y); } - template constexpr inline unsigned uclip(const unsigned x) { - enum { m = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1) }; + template + constexpr inline type_t uclip(const type_t x) { + enum : type_t { b = 1ull << (bits - 1), m = b * 2 - 1 }; return (x & m); } - template constexpr inline signed sclamp(const signed x) { - enum { b = 1U << (bits - 1), m = (1U << (bits - 1)) - 1 }; + template + constexpr inline type_t sclamp(const type_t x) { + enum : type_t { b = 1ull << (bits - 1), m = b - 1 }; return (x > m) ? m : (x < -b) ? -b : x; } - template constexpr inline signed sclip(const signed x) { - enum { b = 1U << (bits - 1), m = (1U << bits) - 1 }; + template + constexpr inline type_t sclip(const type_t x) { + typedef typename type_if::value, unsigned, uintmax_t>::type cast_t; + enum : cast_t { b = 1ull << (bits - 1), m = b * 2 - 1 }; return ((x & m) ^ b) - b; } namespace bit { //lowest(0b1110) == 0b0010 - template constexpr inline T lowest(const T x) { + template + constexpr inline T lowest(const T x) { return x & -x; } //clear_lowest(0b1110) == 0b1100 - template constexpr inline T clear_lowest(const T x) { + template + constexpr inline T clear_lowest(const T x) { return x & (x - 1); } //set_lowest(0b0101) == 0b0111 - template constexpr inline T set_lowest(const T x) { + template + constexpr inline T set_lowest(const T x) { return x | (x + 1); } //count number of bits set in a byte - inline unsigned count(unsigned x) { + template + inline unsigned count(T x) { unsigned count = 0; do count += x & 1; while(x >>= 1); return count; @@ -47,7 +58,8 @@ namespace nall { //round up to next highest single bit: //round(15) == 16, round(16) == 16, round(17) == 32 - inline unsigned round(unsigned x) { + template + inline T round(T x) { if((x & (x - 1)) == 0) return x; while(x & (x - 1)) x &= x - 1; return x << 1; diff --git a/bsnes/nall/platform.hpp b/bsnes/nall/platform.hpp index f3e4b3f5..e775ab8f 100755 --- a/bsnes/nall/platform.hpp +++ b/bsnes/nall/platform.hpp @@ -64,8 +64,8 @@ #define mkdir(n, m) _wmkdir(nall::utf16_t(n)) #define putenv _putenv #define rmdir _rmdir - #define usleep(n) Sleep(n / 1000) #define vsnprintf _vsnprintf + inline void usleep(unsigned milliseconds) { Sleep(milliseconds / 1000); } #endif //================ diff --git a/bsnes/nall/varint.hpp b/bsnes/nall/varint.hpp index be954c62..20f579b6 100755 --- a/bsnes/nall/varint.hpp +++ b/bsnes/nall/varint.hpp @@ -2,61 +2,67 @@ #define NALL_VARINT_HPP #include +#include namespace nall { template class uint_t { private: - unsigned data; + typedef typename type_if::type type_t; + type_t data; public: - inline operator unsigned() const { return data; } - inline unsigned operator ++(int) { unsigned r = data; data = uclip(data + 1); return r; } - inline unsigned operator --(int) { unsigned r = data; data = uclip(data - 1); return r; } - inline unsigned operator ++() { return data = uclip(data + 1); } - inline unsigned operator --() { return data = uclip(data - 1); } - inline unsigned operator =(const unsigned i) { return data = uclip(i); } - inline unsigned operator |=(const unsigned i) { return data = uclip(data | i); } - inline unsigned operator ^=(const unsigned i) { return data = uclip(data ^ i); } - inline unsigned operator &=(const unsigned i) { return data = uclip(data & i); } - inline unsigned operator<<=(const unsigned i) { return data = uclip(data << i); } - inline unsigned operator>>=(const unsigned i) { return data = uclip(data >> i); } - inline unsigned operator +=(const unsigned i) { return data = uclip(data + i); } - inline unsigned operator -=(const unsigned i) { return data = uclip(data - i); } - inline unsigned operator *=(const unsigned i) { return data = uclip(data * i); } - inline unsigned operator /=(const unsigned i) { return data = uclip(data / i); } - inline unsigned operator %=(const unsigned i) { return data = uclip(data % i); } + inline operator type_t() const { return data; } + inline type_t operator ++(int) { type_t r = data; data = uclip(data + 1); return r; } + inline type_t operator --(int) { type_t r = data; data = uclip(data - 1); return r; } + inline type_t operator ++() { return data = uclip(data + 1); } + inline type_t operator --() { return data = uclip(data - 1); } + inline type_t operator =(const type_t i) { return data = uclip(i); } + inline type_t operator |=(const type_t i) { return data = uclip(data | i); } + inline type_t operator ^=(const type_t i) { return data = uclip(data ^ i); } + inline type_t operator &=(const type_t i) { return data = uclip(data & i); } + inline type_t operator<<=(const type_t i) { return data = uclip(data << i); } + inline type_t operator>>=(const type_t i) { return data = uclip(data >> i); } + inline type_t operator +=(const type_t i) { return data = uclip(data + i); } + inline type_t operator -=(const type_t i) { return data = uclip(data - i); } + inline type_t operator *=(const type_t i) { return data = uclip(data * i); } + inline type_t operator /=(const type_t i) { return data = uclip(data / i); } + inline type_t operator %=(const type_t i) { return data = uclip(data % i); } inline uint_t() : data(0) {} - inline uint_t(const unsigned i) : data(uclip(i)) {} + inline uint_t(const type_t i) : data(uclip(i)) {} - template inline unsigned operator=(const uint_t &i) { return data = uclip((unsigned)i); } - template inline uint_t(const uint_t &i) : data(uclip(i)) {} + template inline type_t operator=(const uint_t &i) { return data = uclip((type_t)i); } + template inline uint_t(const uint_t &i) : data(uclip(i)) {} }; template class int_t { private: - signed data; + typedef typename type_if::type type_t; + type_t data; public: - inline operator signed() const { return data; } - inline signed operator ++(int) { signed r = data; data = sclip(data + 1); return r; } - inline signed operator --(int) { signed r = data; data = sclip(data - 1); return r; } - inline signed operator ++() { return data = sclip(data + 1); } - inline signed operator --() { return data = sclip(data - 1); } - inline signed operator =(const signed i) { return data = sclip(i); } - inline signed operator |=(const signed i) { return data = sclip(data | i); } - inline signed operator ^=(const signed i) { return data = sclip(data ^ i); } - inline signed operator &=(const signed i) { return data = sclip(data & i); } - inline signed operator<<=(const signed i) { return data = sclip(data << i); } - inline signed operator>>=(const signed i) { return data = sclip(data >> i); } - inline signed operator +=(const signed i) { return data = sclip(data + i); } - inline signed operator -=(const signed i) { return data = sclip(data - i); } - inline signed operator *=(const signed i) { return data = sclip(data * i); } - inline signed operator /=(const signed i) { return data = sclip(data / i); } - inline signed operator %=(const signed i) { return data = sclip(data % i); } + inline operator type_t() const { return data; } + inline type_t operator ++(int) { type_t r = data; data = sclip(data + 1); return r; } + inline type_t operator --(int) { type_t r = data; data = sclip(data - 1); return r; } + inline type_t operator ++() { return data = sclip(data + 1); } + inline type_t operator --() { return data = sclip(data - 1); } + inline type_t operator =(const type_t i) { return data = sclip(i); } + inline type_t operator |=(const type_t i) { return data = sclip(data | i); } + inline type_t operator ^=(const type_t i) { return data = sclip(data ^ i); } + inline type_t operator &=(const type_t i) { return data = sclip(data & i); } + inline type_t operator<<=(const type_t i) { return data = sclip(data << i); } + inline type_t operator>>=(const type_t i) { return data = sclip(data >> i); } + inline type_t operator +=(const type_t i) { return data = sclip(data + i); } + inline type_t operator -=(const type_t i) { return data = sclip(data - i); } + inline type_t operator *=(const type_t i) { return data = sclip(data * i); } + inline type_t operator /=(const type_t i) { return data = sclip(data / i); } + inline type_t operator %=(const type_t i) { return data = sclip(data % i); } inline int_t() : data(0) {} - inline int_t(const signed i) : data(sclip(i)) {} + inline int_t(const type_t i) : data(sclip(i)) {} + + template inline type_t operator=(const int_t &i) { return data = sclip((type_t)i); } + template inline int_t(const int_t &i) : data(sclip(i)) {} }; class varuint_t { diff --git a/bsnes/nes/video/video.cpp b/bsnes/nes/video/video.cpp index f90626a3..910b3c1e 100755 --- a/bsnes/nes/video/video.cpp +++ b/bsnes/nes/video/video.cpp @@ -46,9 +46,10 @@ unsigned Video::palette30( q *= saturation; auto gammaAdjust = [=](double f) { return f < 0.0 ? 0.0 : std::pow(f, 2.2 / gamma); }; - return (uclamp<10>(1023.0 * gammaAdjust(y + 0.946882 * i + 0.623557 * q)) << 20) - + (uclamp<10>(1023.0 * gammaAdjust(y + -0.274788 * i + -0.635691 * q)) << 10) - + (uclamp<10>(1023.0 * gammaAdjust(y + -1.108545 * i + 1.709007 * q)) << 0); + unsigned r = 1023.0 * gammaAdjust(y + 0.946882 * i + 0.623557 * q); + unsigned g = 1023.0 * gammaAdjust(y + -0.274788 * i + -0.635691 * q); + unsigned b = 1023.0 * gammaAdjust(y + -1.108545 * i + 1.709007 * q); + return (uclamp<10>(r) << 20) + (uclamp<10>(g) << 10) + (uclamp<10>(b) << 0); } void Video::generate(Format format) { diff --git a/bsnes/snes/chip/armdsp/armdsp.cpp b/bsnes/snes/chip/armdsp/armdsp.cpp index 4fde7ee4..37f3060f 100755 --- a/bsnes/snes/chip/armdsp/armdsp.cpp +++ b/bsnes/snes/chip/armdsp/armdsp.cpp @@ -44,7 +44,7 @@ void ArmDSP::enter() { pipeline.prefetch.opcode = bus_read<4>(r[15]); r[15].step(); - //if(pipeline.instruction.address == 0x00000208) trace = 1; + //if(pipeline.instruction.address == 0x0000ef5c) trace = 1; if(trace) { print("\n", disassemble_registers(), "\n"); print(disassemble_opcode(pipeline.instruction.address), "\n"); @@ -52,6 +52,7 @@ void ArmDSP::enter() { } instruction = pipeline.instruction.opcode; + if(!condition()) continue; if((instruction & 0x0fc000f0) == 0x00000090) { op_multiply(); continue; } if((instruction & 0x0fb000f0) == 0x01000000) { op_move_to_register_from_status_register(); continue; } if((instruction & 0x0fb000f0) == 0x01200000) { op_move_to_status_register_from_register(); continue; } diff --git a/bsnes/snes/chip/armdsp/armdsp.hpp b/bsnes/snes/chip/armdsp/armdsp.hpp index 7718a345..50fc2e9b 100755 --- a/bsnes/snes/chip/armdsp/armdsp.hpp +++ b/bsnes/snes/chip/armdsp/armdsp.hpp @@ -1,4 +1,4 @@ -//ARM v3 (ARM6?) +//ARMv3 (ARM6) struct ArmDSP : public Coprocessor { uint8 programROM[128 * 1024]; @@ -22,6 +22,11 @@ struct ArmDSP : public Coprocessor { //opcodes.cpp bool condition(); void opcode(uint32 data); + void lsl(bool &c, uint32 &rm, uint32 rs); + void lsr(bool &c, uint32 &rm, uint32 rs); + void asr(bool &c, uint32 &rm, uint32 rs); + void ror(bool &c, uint32 &rm, uint32 rs); + void rrx(bool &c, uint32 &rm); void op_multiply(); void op_move_to_status_register_from_register(); diff --git a/bsnes/snes/chip/armdsp/disassembler.cpp b/bsnes/snes/chip/armdsp/disassembler.cpp index 71a94fcb..8a7f046b 100755 --- a/bsnes/snes/chip/armdsp/disassembler.cpp +++ b/bsnes/snes/chip/armdsp/disassembler.cpp @@ -15,24 +15,49 @@ string ArmDSP::disassemble_opcode(uint32 pc) { uint32 instruction = bus_read<4>(pc); output.append(hex<8>(instruction), " "); + //multiply + if((instruction & 0x0fc000f0) == 0x00000090) { + uint4 condition = instruction >> 28; + uint1 accumulate = instruction >> 21; + uint1 save = instruction >> 20; + uint4 rd = instruction >> 16; + uint4 rn = instruction >> 12; + uint4 rs = instruction >> 8; + uint4 rm = instruction >> 0; + + output.append(accumulate ? "mla" : "mul", condition[conditions], save ? "s " : " "); + output.append(registers[rd], ",", registers[rm], ",", registers[rs]); + if(accumulate) output.append(",", registers[rn]); + + return output; + } + //move to register from status register if((instruction & 0x0fb000f0) == 0x01000000) { + uint4 condition = instruction >> 28; uint1 psr = instruction >> 22; uint4 rd = instruction >> 12; - output.append("mrs ", registers[rd], ",", psr ? "spsr" : "cpsr"); + + output.append("mrs", condition[conditions], " "); + output.append(registers[rd], ",", psr ? "spsr" : "cpsr"); + return output; } //move to status register from register if((instruction & 0x0fb000f0) == 0x01200000) { + uint4 condition = instruction >> 28; uint1 psr = instruction >> 22; uint4 field = instruction >> 16; - output.append("msr ", psr ? "spsr:" : "cpsr:", + + output.append("msr", conditions[condition], " "); + output.append(psr ? "spsr:" : "cpsr:", field & 1 ? "c" : "", field & 2 ? "x" : "", field & 4 ? "s" : "", field & 8 ? "f" : "", ",", registers[(uint4)instruction]); + return output; } diff --git a/bsnes/snes/chip/armdsp/opcodes.cpp b/bsnes/snes/chip/armdsp/opcodes.cpp index 8ff6b1e7..3fda67b6 100755 --- a/bsnes/snes/chip/armdsp/opcodes.cpp +++ b/bsnes/snes/chip/armdsp/opcodes.cpp @@ -1,7 +1,8 @@ #ifdef ARMDSP_CPP bool ArmDSP::condition() { - switch((uint4)(instruction >> 28)) { + uint4 condition = instruction >> 28; + switch(condition) { case 0: return cpsr.z == 1; //EQ (equal) case 1: return cpsr.z == 0; //NE (not equal) case 2: return cpsr.c == 1; //CS (carry set) @@ -29,33 +30,36 @@ bool ArmDSP::condition() { void ArmDSP::opcode(uint32 rm) { uint4 opcode = instruction >> 21; uint1 s = instruction >> 20; - auto &rn = r[(uint4)(instruction >> 16)]; - auto &rd = r[(uint4)(instruction >> 12)]; + 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); - static auto bit = [&](uint32 ro) { + auto bit = [&](uint32 ro) { if(!s) return; - cpsr.n = ro & 0x80000000; + cpsr.n = ro >> 31; cpsr.z = ro == 0; }; - static auto add = [&](uint32 ro) { + auto add = [&](uint32 ro) { if(!s) return; - cpsr.n = ro & 0x80000000; + cpsr.n = ro >> 31; cpsr.z = ro == 0; cpsr.c = ro < ri; - cpsr.v = ~(ri ^ rm) & (ri ^ ro) & 0x80000000; + cpsr.v = ~(ri ^ rm) & (ri ^ ro) & (1u << 31); }; - static auto sub = [&](uint32 ro) { + auto sub = [&](uint32 ro) { if(!s) return; - cpsr.n = ro & 0x80000000; + cpsr.n = ro >> 31; cpsr.z = ro == 0; cpsr.c = ro > ri; - cpsr.v = (ri ^ rm) & (ri ^ ro) & 0x80000000; + cpsr.v = (ri ^ rm) & (ri ^ ro) & (1u << 31); }; switch(opcode) { @@ -78,7 +82,46 @@ void ArmDSP::opcode(uint32 rm) { } } -//(mul,mla){condition}{s} +//logical shift left +void ArmDSP::lsl(bool &c, uint32 &rm, uint32 rs) { + while(rs--) { + c = rm >> 31; + rm <<= 1; + } +} + +//logical shift right +void ArmDSP::lsr(bool &c, uint32 &rm, uint32 rs) { + while(rs--) { + c = rm & 1; + rm >>= 1; + } +} + +//arithmetic shift right +void ArmDSP::asr(bool &c, uint32 &rm, uint32 rs) { + while(rs--) { + c = rm & 1; + rm = (int32)rm >> 1; + } +} + +//rotate right +void ArmDSP::ror(bool &c, uint32 &rm, uint32 rs) { + while(rs--) { + c = rm & 1; + rm = (rm << 31) | (rm >> 1); + } +} + +//rotate right with extend +void ArmDSP::rrx(bool &c, uint32 &rm) { + bool carry = c; + c = rm & 1; + rm = (carry << 31) | (rm >> 1); +} + +//(mul,mla){condition}{s} rd,rm,rs,rn //cccc 0000 00as dddd nnnn ssss 1001 mmmm //c = condition //a = accumulate @@ -88,8 +131,6 @@ void ArmDSP::opcode(uint32 rm) { //s = rs //n = rm void ArmDSP::op_multiply() { - if(!condition()) return; - uint1 accumulate = instruction >> 21; uint1 save = instruction >> 20; uint4 d = instruction >> 16; @@ -100,7 +141,7 @@ void ArmDSP::op_multiply() { r[d] = r[m] * r[s]; if(accumulate) r[d] += r[n]; if(save) { - cpsr.n = r[d] & 0x80000000; + cpsr.n = r[d] >> 31; cpsr.z = r[d] == 0; } } @@ -111,8 +152,6 @@ void ArmDSP::op_multiply() { //r = SPSR (0 = CPSR) //d = rd void ArmDSP::op_move_to_register_from_status_register() { - if(!condition()) return; - uint1 source = instruction >> 22; uint4 d = instruction >> 12; @@ -126,8 +165,6 @@ void ArmDSP::op_move_to_register_from_status_register() { //f = field mask //m = rm void ArmDSP::op_move_to_status_register_from_register() { - if(!condition()) return; - uint1 source = instruction >> 22; uint4 field = instruction >> 16; uint4 m = instruction; @@ -152,44 +189,27 @@ void ArmDSP::op_move_to_status_register_from_register() { //s = shift //m = rm void ArmDSP::op_data_immediate_shift() { - if(!condition()) return; - uint1 save = instruction >> 20; uint5 shift = instruction >> 7; uint2 mode = instruction >> 5; uint4 m = instruction; - bool carry = cpsr.c; uint32 rs = shift; uint32 rm = r[m]; + bool c = cpsr.c; - switch(mode) { - case 0: //LSL - rm = rm << rs; - if(rs) carry = rm & (1 << (32 - rs)); - break; + if(mode == 0) lsl(c, rm, rs); + if(mode == 1) lsr(c, rm, rs ? rs : 32); + if(mode == 2) asr(c, rm, rs ? rs : 32); + if(mode == 3) rs ? ror(c, rm, rs) : rrx(c, rm); - case 1: //LSR - if(rs == 0) rs = 32; - rm = rm >> rs; - carry = rm & (1 << (rs - 1)); - break; - - case 2: //ASR - if(rs == 0) rs = 32; - rm = (int32)rm >> rs; - break; - - case 3: //ROR + RRX - if(rs == 0) rm = (cpsr.c << 31) | (rm >> 1); //RRX - if(rs != 0) rm = (rm >> rs) + (rm << (32 - rs)); //ROR - break; - } - - if(save) cpsr.c = carry; + if(save) cpsr.c = c; opcode(rm); } +//{opcode}{condition}{s} rd,rm {shift} rs +//{opcode}{condition} rn,rm {shift} rs +//{opcode}{condition}{s} rd,rn,rm {shift} rs //cccc 000o ooos nnnn dddd ssss 0ss1 mmmm //c = condition //o = opcode @@ -200,39 +220,21 @@ void ArmDSP::op_data_immediate_shift() { //s = shift //m = rm void ArmDSP::op_data_register_shift() { - if(!condition()) return; - uint1 save = instruction >> 20; uint4 s = instruction >> 8; uint2 mode = instruction >> 5; uint4 m = instruction >> 0; - bool carry = cpsr.c; - uint32 rs = (uint8)r[s]; + uint8 rs = r[s]; uint32 rm = r[m]; + bool c = cpsr.c; - switch(mode) { - case 0: //LSL - rm = rm << rs; - if(rs) carry = rm & (1 << (32 - rs)); - break; + 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); - case 1: //LSR - if(rs == 0) break; - rm = rm >> rs; - carry = rm & (1 << (rs - 1)); - break; - - case 2: //ASR - rm = (int32)rm >> rs; - break; - - case 3: //ROR - rm = (rm >> rs) + (rm << (32 - rs)); - break; - } - - if(save) cpsr.c = carry; + if(save) cpsr.c = c; opcode(rm); } @@ -248,18 +250,17 @@ void ArmDSP::op_data_register_shift() { //l = shift immediate //i = immediate void ArmDSP::op_data_immediate() { - if(!condition()) return; - uint1 save = instruction >> 20; uint4 shift = instruction >> 8; uint8 immediate = instruction; - bool carry = cpsr.c; + bool c = cpsr.c; + uint32 rs = shift << 1; uint32 rm = (immediate >> rs) | (immediate << (32 - rs)); - if(rs) carry = immediate & 0x80000000; + if(rs) c = immediate >> 31; - if(save) cpsr.c = carry; + if(save) cpsr.c = c; opcode(rm); } @@ -275,8 +276,6 @@ void ArmDSP::op_data_immediate() { //d = rd //i = immediate void ArmDSP::op_move_immediate_offset() { - if(!condition()) return; - uint1 p = instruction >> 24; uint1 u = instruction >> 23; uint1 b = instruction >> 22; @@ -318,8 +317,6 @@ void ArmDSP::op_move_immediate_offset() { //s = shift mode //m = rm void ArmDSP::op_move_register_offset() { - if(!condition()) return; - uint1 p = instruction >> 24; uint1 u = instruction >> 23; uint1 b = instruction >> 22; @@ -335,27 +332,12 @@ void ArmDSP::op_move_register_offset() { auto &rd = r[d]; uint32 rs = immediate; uint32 rm = r[m]; + bool c = cpsr.c; - switch(mode) { - case 0: //LSL - rm = rm << rs; - break; - - case 1: //LSR - if(rs == 0) rs = 32; - rm = rm >> rs; - break; - - case 2: //ASR - if(rs == 0) rs = 32; - rm = (int32)rm >> rs; - break; - - case 3: //ROR + RRX - if(rs == 0) rm = (cpsr.c << 31) | (rm >> 1); //RRX - if(rs != 0) rm = (rm >> rs) + (rm << (32 - rs)); //ROR - break; - } + if(mode == 0) lsl(c, rm, rs); + if(mode == 1) lsr(c, rm, rs ? rs : 32); + 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; @@ -372,6 +354,7 @@ void ArmDSP::op_move_register_offset() { if(p == 0 || w == 1) r[n] = rn; } +//(ldm,stm){condition}{mode} rn{!},{r...} //cccc 100p uswl nnnn llll llll llll llll //c = condition //p = pre (0 = post-indexed addressing) @@ -382,8 +365,6 @@ void ArmDSP::op_move_register_offset() { //n = rn //l = register list void ArmDSP::op_move_multiple() { - if(!condition()) return; - uint1 p = instruction >> 24; uint1 u = instruction >> 23; uint1 s = instruction >> 22; @@ -426,8 +407,6 @@ void ArmDSP::op_move_multiple() { //l = link //d = displacement (24-bit signed) void ArmDSP::op_branch() { - if(!condition()) return; - uint1 l = instruction >> 24; int24 displacement = instruction; diff --git a/bsnes/snes/chip/armdsp/registers.hpp b/bsnes/snes/chip/armdsp/registers.hpp index d9600e04..6f3d28ba 100755 --- a/bsnes/snes/chip/armdsp/registers.hpp +++ b/bsnes/snes/chip/armdsp/registers.hpp @@ -16,7 +16,7 @@ struct Bridge { Buffer armtocpu; uint8 status() const { - return 0x80 | (cputoarm.ready << 3) | (armtocpu.ready << 0); + return 0x84 | (cputoarm.ready << 3) | (armtocpu.ready << 0); } } bridge; diff --git a/bsnes/snes/chip/msu1/msu1.cpp b/bsnes/snes/chip/msu1/msu1.cpp index f12a9102..b1695e65 100755 --- a/bsnes/snes/chip/msu1/msu1.cpp +++ b/bsnes/snes/chip/msu1/msu1.cpp @@ -36,8 +36,10 @@ void MSU1::enter() { } } - left = sclamp<16>((double)left * (double)mmio.audio_volume / 255.0); - right = sclamp<16>((double)right * (double)mmio.audio_volume / 255.0); + signed lchannel = (double)left * (double)mmio.audio_volume / 255.0; + signed rchannel = (double)right * (double)mmio.audio_volume / 255.0; + left = sclamp<16>(lchannel); + right = sclamp<16>(rchannel); audio.coprocessor_sample(left, right); step(1);