From 3ed42af8a141a7941bc2b6ac56c3176219845442 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Mon, 27 Feb 2012 11:18:50 +1100 Subject: [PATCH] Update to v086r09 release. byuu says: A lot more work on the ARMv3 core. --- bsnes/base/base.hpp | 2 +- bsnes/nall/bit.hpp | 7 + bsnes/snes/chip/armdsp/armdsp.cpp | 64 +++++-- bsnes/snes/chip/armdsp/armdsp.hpp | 15 +- bsnes/snes/chip/armdsp/disassembler.cpp | 81 ++++++++- bsnes/snes/chip/armdsp/memory.cpp | 58 +++++- bsnes/snes/chip/armdsp/opcodes.cpp | 229 ++++++++++++++++++++---- bsnes/snes/chip/armdsp/registers.hpp | 75 +++++++- 8 files changed, 459 insertions(+), 72 deletions(-) diff --git a/bsnes/base/base.hpp b/bsnes/base/base.hpp index be888faf..7bc21c87 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.08"; +const char Version[] = "086.09"; #include #include diff --git a/bsnes/nall/bit.hpp b/bsnes/nall/bit.hpp index 67a35ad6..d5e5e1bd 100755 --- a/bsnes/nall/bit.hpp +++ b/bsnes/nall/bit.hpp @@ -38,6 +38,13 @@ namespace nall { return x | (x + 1); } + //count number of bits set in a byte + inline unsigned count(unsigned x) { + unsigned count = 0; + do count += x & 1; while(x >>= 1); + return count; + } + //round up to next highest single bit: //round(15) == 16, round(16) == 16, round(17) == 32 inline unsigned round(unsigned x) { diff --git a/bsnes/snes/chip/armdsp/armdsp.cpp b/bsnes/snes/chip/armdsp/armdsp.cpp index cb713d97..d74b722c 100755 --- a/bsnes/snes/chip/armdsp/armdsp.cpp +++ b/bsnes/snes/chip/armdsp/armdsp.cpp @@ -17,30 +17,61 @@ void ArmDSP::enter() { scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); } - step(16); + step(4); //todo: how many cycles per instruction? synchronize_cpu(); - print(disassemble_opcode(r[15]), "\n", disassemble_registers(), "\n"); - - instruction = bus_read(r[15]); - r[15] += 8; //pipeline adjust - if((instruction & 0x0e000000) == 0x0a000000) { op_branch(); continue; } - if((instruction & 0x0e000000) == 0x02000000) { op_data_immediate(); r[15] -= 4; continue; } - - print("* ARM unknown instruction\n"); - while(true) { - step(21477272); - synchronize_cpu(); + if(exception) { + print("* ARM unknown instruction\n"); + print("\n", disassemble_registers()); + print("\n", disassemble_opcode(pipeline.instruction.address), "\n"); + while(true) { + step(21477272); + synchronize_cpu(); + } } + + if(pipeline.reload) { + pipeline.reload = false; + pipeline.prefetch.address = r[15]; + pipeline.prefetch.opcode = bus_read<4>(r[15]); + r[15].step(); + } + + pipeline.instruction = pipeline.prefetch; + pipeline.prefetch.address = r[15]; + pipeline.prefetch.opcode = bus_read<4>(r[15]); + r[15].step(); + + //print("\n", disassemble_registers(), "\n"); + //print(disassemble_opcode(pipeline.instruction.address), "\n"); + + instruction = pipeline.instruction.opcode; + if((instruction & 0x0fb000f0) == 0x01200000) { op_move_status_register_to_register(); continue; } + if((instruction & 0x0e000010) == 0x00000000) { op_data_immediate_shift(); continue; } + if((instruction & 0x0e000000) == 0x02000000) { op_data_immediate(); continue; } + if((instruction & 0x0e000000) == 0x04000000) { op_move_immediate_offset(); continue; } + if((instruction & 0x0e000000) == 0x08000000) { op_move_multiple(); continue; } + if((instruction & 0x0e000000) == 0x0a000000) { op_branch(); continue; } + + exception = true; } } uint8 ArmDSP::mmio_read(unsigned addr) { -//print("* r", hex<4>(addr), "\n"); + addr &= 0xffff; + if(addr == 0x3800) return armport[0]; + if(addr == 0x3802) return armport[1]; + if(addr == 0x3804) return armport[3]; + + print("* r", hex<4>(addr), "\n"); return 0x00; } void ArmDSP::mmio_write(unsigned addr, uint8 data) { + addr &= 0xffff; + if(addr == 0x3802) cpuport[1] = data; + if(addr == 0x3804) cpuport[0] = data; + print("* w", hex<4>(addr), "w = ", hex<2>(data), "\n"); } @@ -59,7 +90,12 @@ void ArmDSP::power() { void ArmDSP::reset() { create(ArmDSP::Enter, 21477272); - for(auto &rd : r) rd = 0x00000000; + for(auto &rd : r) rd = 0; + exception = false; + + pipeline.reload = true; + + r[15].write = [&] { pipeline.reload = true; }; } } diff --git a/bsnes/snes/chip/armdsp/armdsp.hpp b/bsnes/snes/chip/armdsp/armdsp.hpp index bf8ef7fb..b46fcc48 100755 --- a/bsnes/snes/chip/armdsp/armdsp.hpp +++ b/bsnes/snes/chip/armdsp/armdsp.hpp @@ -2,9 +2,13 @@ struct ArmDSP : public Coprocessor { uint8 programROM[128 * 1024]; + uint8 programRAM[16 * 1024]; #include "registers.hpp" + uint8 cpuport[4]; + uint8 armport[4]; + static void Enter(); void enter(); @@ -19,16 +23,21 @@ struct ArmDSP : public Coprocessor { //opcodes.cpp bool condition(); - void opcode(uint32 &rd, uint32 &rn, uint32 shifter); + void opcode(uint32 data); void flags(uint32 rd); void op_branch(); void op_data_immediate(); + void op_data_immediate_shift(); void op_move_immediate_offset(); + void op_move_status_register_to_register(); + void op_move_multiple(); //memory.cpp - uint32 bus_read(uint32 addr); - void bus_write(uint32 addr, uint32 data); + 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); //disassembler.cpp string disassemble_opcode(uint32 pc); diff --git a/bsnes/snes/chip/armdsp/disassembler.cpp b/bsnes/snes/chip/armdsp/disassembler.cpp index 85d63d76..fe0612e8 100755 --- a/bsnes/snes/chip/armdsp/disassembler.cpp +++ b/bsnes/snes/chip/armdsp/disassembler.cpp @@ -1,12 +1,14 @@ #ifdef ARMDSP_CPP string ArmDSP::disassemble_opcode(uint32 pc) { - static string conditions[] = { "eq", "ne", "cs", "cc", "mi" ,"pl", "vs", "vc", "hi", "ls", "ge", "lt", "gt", "le", "al", "nv" }; + static string conditions[] = { "eq", "ne", "cs", "cc", "mi" ,"pl", "vs", "vc", "hi", "ls", "ge", "lt", "gt", "le", "" /*al*/, "nv" }; static string opcodes[] = { "and", "eor", "sub", "rsb", "add", "adc", "sbc", "rsc", "tst", "teq", "cmp", "cmn", "orr", "mov", "bic", "mvn" }; + static string registers[] = { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" }; + static string indices[] = { "da", "ia", "db", "ib" }; string output{hex<8>(pc), " "}; - uint32 instruction = bus_read(pc); + uint32 instruction = bus_read<4>(pc); output.append(hex<8>(instruction), " "); uint4 condition = instruction >> 28; @@ -15,18 +17,80 @@ string ArmDSP::disassemble_opcode(uint32 pc) { uint4 rd = instruction >> 12; uint4 rs = instruction >> 8; - if((instruction & 0x0e000000) == 0x0a000000) { - output.append("b"); - if(condition != 14) output.append(conditions[condition]); - output.append(" 0x", hex<8>(pc + 8 + (int24)instruction * 4)); + //move status register to register + if((instruction & 0x0fb000f0) == 0x01200000) { + uint1 psr = instruction >> 22; + uint4 field = instruction >> 16; + output.append("msr ", psr ? "spsr:" : "cpsr:", + field & 1 ? "c" : "", + field & 2 ? "x" : "", + field & 4 ? "s" : "", + field & 8 ? "f" : "", + ",", registers[(uint4)instruction]); return output; } + //data immediate shift + if((instruction & 0x0e000000) == 0x00000000) { + uint4 condition = instruction >> 28; + uint4 opcode = instruction >> 21; + uint1 save = instruction >> 20; + uint4 rd = instruction >> 16; + uint4 rn = instruction >> 12; + uint8 rm = instruction; + uint5 shift = instruction >> 7; + uint2 op = instruction >> 2; + + output.append(opcodes[opcode], conditions[condition], save ? "s " : " "); + output.append(registers[rd], ","); + output.append(registers[rn], ","); + output.append(registers[rm], " "); + if(op == 0) output.append("lsl #", shift); + if(op == 1) output.append("lsr #", 1 + shift); + if(op == 2) output.append("asr #", 1 + shift); + if(op == 3 && shift != 0) output.append("ror #", shift); + if(op == 3 && shift == 0) output.append("rrx"); + + return output; + } + + //data immediate if((instruction & 0x0e000000) == 0x02000000) { uint5 rotate = 2 * (uint4)(instruction >> 8); uint32 immediate = (uint8)instruction; immediate = (immediate >> rotate) | (immediate << (32 - rotate)); - output.append(opcodes[opcode], " r", rd, ",#0x", hex<8>(immediate)); + output.append(opcodes[opcode], " ", registers[rd], ",#0x", hex<8>(immediate)); + return output; + } + + //move immediate offset + //todo: support W flag + if((instruction & 0x0e000000) == 0x04000000) { + uint1 u = instruction >> 23; + uint1 load = instruction >> 20; + uint12 immediate = instruction; + output.append(load ? "ldr" : "str", conditions[condition]); + output.append(" ", registers[rd], ",[", registers[rn]); + if(immediate) output.append(u ? "+" : "-", "0x", hex<3>((uint12)instruction)); + output.append("]"); + return output; + } + + //move multiple + if((instruction & 0x0e000000) == 0x08000000) { + output.append(instruction & 0x00100000 ? "ldm" : "stm", conditions[condition], indices[(uint2)(instruction >> 23)]); + output.append(" ", registers[rn], instruction & 0x00200000 ? "!" : "", ",{"); + for(unsigned n = 0; n < 16; n++) if(instruction & (1 << n)) output.append(registers[n], ","); + output.rtrim<1>(","); + output.append("}"); + return output; + } + + //branch + if((instruction & 0x0e000000) == 0x0a000000) { + uint1 l = instruction >> 24; + output.append("b", l ? "l" : "", conditions[condition]); + output.append(" 0x", hex<8>(pc + 8 + (int24)instruction * 4)); return output; } @@ -39,7 +103,8 @@ string ArmDSP::disassemble_registers() { "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", "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" + " 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" }; } diff --git a/bsnes/snes/chip/armdsp/memory.cpp b/bsnes/snes/chip/armdsp/memory.cpp index af30cd57..acedc2af 100755 --- a/bsnes/snes/chip/armdsp/memory.cpp +++ b/bsnes/snes/chip/armdsp/memory.cpp @@ -1,18 +1,62 @@ #ifdef ARMDSP_CPP -uint32 ArmDSP::bus_read(uint32 addr) { +uint8 ArmDSP::bus_iread(uint32 addr) { if(addr >= 0x00000000 && addr <= 0x0001ffff) { - addr &= 0x0001ffff; - return (programROM[addr + 0] << 0) - + (programROM[addr + 1] << 8) - + (programROM[addr + 2] << 16) - + (programROM[addr + 3] << 24); + return programROM[addr & 0x0001ffff]; } - return 0x00000000; + if(addr >= 0x40000020 && addr <= 0x4000002f) { + if(addr == 0x40000020) return cpuport[0]; + if(addr == 0x40000024) return cpuport[1]; + if(addr == 0x40000028) return cpuport[2]; + if(addr == 0x4000002c) return cpuport[3]; + } + + if(addr >= 0xe0000000 && addr <= 0xe0003fff) { + return programRAM[addr & 0x00003fff]; + } + +//print("* ARM r", hex<8>(addr), "\n"); + return 0x00; } +void ArmDSP::bus_iwrite(uint32 addr, uint8 data) { + if(addr >= 0x40000020 && addr <= 0x4000002f) { + if(addr == 0x40000020) armport[0] = data; + if(addr == 0x40000024) armport[1] = data; + if(addr == 0x40000028) armport[2] = data; + if(addr == 0x4000002c) armport[3] = data; +if(data) print("* ARM w", hex<8>(addr), " = ", hex<2>(data), "\n"); + } + + if(addr >= 0xe0000000 && addr <= 0xe0003fff) { + programRAM[addr & 0x00003fff] = data; + return; + } + +//print("* ARM w", hex<8>(addr), " = ", hex<2>(data), "\n"); +} + +template +uint32 ArmDSP::bus_read(uint32 addr) { + uint32 result = 0; + result |= bus_iread(addr + 0) << 0; + result |= bus_iread(addr + 1) << 8; + result |= bus_iread(addr + 2) << 16; + result |= bus_iread(addr + 3) << 24; + if(size == 1) return result & 0xff; + if(size == 2) return result & 0xffff; + return result; +} + +template void ArmDSP::bus_write(uint32 addr, uint32 data) { + if(size == 1) data = (bus_read<1>(addr) & 0xffffff00) | (data & 0x000000ff); + if(size == 2) data = (bus_read<2>(addr) & 0xffff0000) | (data & 0x0000ffff); + 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 9cb87535..dc318919 100755 --- a/bsnes/snes/chip/armdsp/opcodes.cpp +++ b/bsnes/snes/chip/armdsp/opcodes.cpp @@ -21,24 +21,52 @@ bool ArmDSP::condition() { } } -void ArmDSP::opcode(uint32 &rd, uint32 &rn, uint32 shifter) { - switch((uint4)(instruction >> 21)) { - case 0: rd = rn & shifter; break; //AND (logical and) - case 1: rd = rn & shifter; break; //EOR (logical exclusive or) - case 2: rd = rn - shifter; break; //SUB (subtract) - case 3: rd = shifter - rn; break; //RSB (reverse subtract) - case 4: rd = rn + shifter; break; //ADD (add) - case 5: rd = rn + shifter + cpsr.c; break; //ADC (add with carry) - case 6: rd = rn - shifter - !cpsr.c; break; //SBC (subtract with carry) - case 7: rd = shifter - rn - !cpsr.c; break; //RSC (reverse subtract with carry) - case 8: flags(rn & shifter); break; //TST (test) - case 9: flags(rn ^ shifter); break; //TEQ (test equivalence) - case 10: flags(rn - shifter); break; //CMP (compare) - case 11: flags(rn + shifter); break; //CMN (compare negated) - case 12: rd = rn | shifter; break; //ORR (logical inclusive or) - case 13: rd = shifter; break; //MOV (move) - case 14: rd = rn & ~shifter; break; //BIC (bit clear) - case 15: rd = ~shifter; //MVN (move not) +//rd = target +//rn = source +//rm = modifier +//ri = original target +//ro = modified target +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)]; + uint32 ri = rd, ro; + + //comparison opcodes always update flags + if(opcode >= 8 && opcode <= 11) s = 1; + + static auto nz = [&](uint32 ro) { + if(!s) return; + cpsr.n = ro & 0x80000000; + cpsr.z = ro == 0; + }; + + static auto nzcv = [&](uint32 ro) { + if(!s) return; + cpsr.n = ro & 0x80000000; + cpsr.z = ro == 0; + cpsr.c = ro < ri; + cpsr.v = ~(ri ^ rm) & (ri ^ ro) & 0x80000000; + }; + + switch(opcode) { + case 0: rd = rn & rm; nz(rd); break; //AND (logical and) + case 1: rd = rn ^ rm; nz(rd); break; //EOR (logical exclusive or) + case 2: rd = rn +~rm; nzcv(rd); break; //SUB (subtract) + case 3: rd = rm +~rn; nzcv(rd); break; //RSB (reverse subtract) + case 4: rd = rn + rm; nzcv(rd); break; //ADD (add) + case 5: rd = rn + rm + cpsr.c; nzcv(rd); break; //ADC (add with carry) + case 6: rd = rn +~rm + cpsr.c; nzcv(rd); break; //SBC (subtract with carry) + case 7: rd = rm +~rn + cpsr.c; nzcv(rd); break; //RSC (reverse subtract with carry) + case 8: ro = rn & rm; nz(ro); break; //TST (test) + case 9: ro = rn ^ rm; nz(ro); break; //TEQ (test equivalence) + case 10: ro = rn +~rm; nzcv(ro); break; //CMP (compare) + case 11: ro = rn + rm; nzcv(ro); break; //CMN (compare negated) + case 12: rd = rn | rm; nz(rd); break; //ORR (logical inclusive or) + case 13: rd = rm; nz(rd); break; //MOV (move) + case 14: rd = rn &~rm; nz(rd); break; //BIC (bit clear) + case 15: rd =~rm; nz(rd); break; //MVN (move not) } } @@ -54,7 +82,10 @@ void ArmDSP::flags(uint32 rd) { void ArmDSP::op_branch() { if(!condition()) return; - int24 displacement = (int24)instruction; + uint1 l = instruction >> 24; + int24 displacement = instruction; + + if(l) r[14] = r[15] - 4; r[15] += displacement * 4; } @@ -69,28 +100,162 @@ void ArmDSP::op_branch() { void ArmDSP::op_data_immediate() { if(!condition()) return; - bool s = (uint1)(instruction >> 20); - uint4 n = (uint4)(instruction >> 16); - uint4 d = (uint4)(instruction >> 12); - uint5 rotate = 2 * (uint4)(instruction >> 8); - uint32 immediate = (uint8)instruction; - immediate = (immediate >> rotate) | (immediate << (32 - rotate)); + uint4 rotate = instruction >> 8; + uint8 immediate = instruction >> 0; - opcode(r[d], r[n], immediate); + opcode( + (immediate >> (rotate << 1)) | (immediate << (32 - (rotate << 1))) + ); + + //todo: set carry for non-add/sub opcodes here } -//CCCC 010P UBWL NNNN DDDD IIII IIII +//CCCC 000O OOOS NNNN DDDD LLLL LSS0 MMMM //C = condition -//P = pre/post-indexed addressing -//U = add/sub offset to base -//B = byte/word access -//W = ... -//L = load/save +//O = opcode +//S = update flags +//N = Rn +//D = Rd +//L = shift amount +//S = shift +//M = Rm +void ArmDSP::op_data_immediate_shift() { + if(!condition()) return; + + uint5 shift = instruction >> 7; + uint2 op = instruction >> 5; + uint32 rm = r[(uint4)instruction]; + + if(op == 0) { //LSL (logical shift left) + rm = rm << shift; + } + + if(op == 1) { //LSR (logical shift right) + rm = rm >> (1 + shift); + } + + if(op == 2) { //ASR (arithmetic shift right) + rm = (int32)rm >> (1 + shift); + } + + if(op == 3) { //ROR (rotate right) + if(shift == 0) { //RRX (rorate right with extend) + rm = (cpsr.c << 31) | (rm >> 1); + } else { + rm = (rm >> shift) + (rm << (32 - shift)); + } + } + + opcode(rm); + + //todo: set carry +} + +//CCCC 010P UBWL NNNN DDDD IIII IIII IIII +//C = condition +//P = pre (0 = post-indexed addressing) +//U = up (add/sub offset to base) +//B = byte (1 = 32-bit) +//W = writeback +//L = load (0 = save) //N = Rn //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; + uint1 w = instruction >> 21; + uint1 l = instruction >> 20; + uint4 n = instruction >> 16; + auto &rd = r[(uint4)(instruction >> 12)]; + uint12 immediate = instruction; + + uint32 rn = r[n]; + + if(l) { + if(p == 1) rn = u ? rn + immediate : rn - immediate; + if(b) rd = bus_read<1>(rn); + else rd = bus_read<4>(rn); + if(p == 0) rn = u ? rn + immediate : rn - immediate; + } else { + if(p == 1) rn = u ? rn + immediate : rn - immediate; + if(b) bus_write<1>(rn, rd); + else bus_write<4>(rn, rd); + if(p == 0) rn = u ? rn + immediate : rn - immediate; + } + + if(p == 1 && w == 1) r[n] = rn; +} + +//CCCC 0001 0R10 FFFF ++++ ---- 0000 MMMM +//C = condition +//R = SPSR (0 = CPSR) +//F = field mask +//M = Rm +void ArmDSP::op_move_status_register_to_register() { + if(!condition()) return; + + uint1 source = instruction >> 22; + uint4 field = instruction >> 16; + + auto &rm = r[(uint4)instruction]; + PSR &psr = source ? spsr : cpsr; + + if(field & 1) psr.setc(rm); + if(field & 2) psr.setx(rm); + if(field & 4) psr.sets(rm); + if(field & 8) psr.setf(rm); +} + +//CCCC 100P USWL NNNN LLLL LLLL LLLL LLLL +//C = condition +//P = pre (0 = post-indexed addressing) +//U = up (add/sub offset to base) +//S = ??? +//W = writeback +//L = load (0 = save) +//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; + uint1 w = instruction >> 21; + uint1 l = instruction >> 20; + uint4 n = instruction >> 16; + uint16 list = instruction; + + uint32 rn; + if(p == 0 && u == 1) rn = r[n] + 0; //IA + if(p == 1 && u == 1) rn = r[n] + 4; //IB + if(p == 1 && u == 0) rn = r[n] - bit::count(list) * 4 + 0; //DB + if(p == 0 && u == 0) rn = r[n] - 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; + } + } + } + + if(w) { + if(u == 1) r[n] = r[n] + bit::count(list) * 4; //IA, IB + if(u == 0) r[n] = r[n] - bit::count(list) * 4; //DA, DB + } } #endif diff --git a/bsnes/snes/chip/armdsp/registers.hpp b/bsnes/snes/chip/armdsp/registers.hpp index 13120cac..a48ede8b 100755 --- a/bsnes/snes/chip/armdsp/registers.hpp +++ b/bsnes/snes/chip/armdsp/registers.hpp @@ -7,7 +7,7 @@ //00000018 = IRQ (interrupt) //0000001c = FIQ (fast interrupt) -struct CPSR { +struct PSR { bool n; bool z; bool c; @@ -16,26 +16,87 @@ struct CPSR { bool f; uint5 m; - operator unsigned() const { - return (n << 31) | (z << 30) | (c << 29) | (v << 28) | (i << 7) | (f << 6) | (m << 0); + uint32 getf() const { + return (n << 31) | (z << 30) | (c << 29) | (v << 28); } - CPSR& operator=(uint32 data) { + uint32 gets() const { + return 0u; + } + + uint32 getx() const { + return 0u; + } + + uint32 getc() const { + return (i << 7) | (f << 6) | (m << 0); + } + + void setf(uint32 data) { n = data & 0x80000000; z = data & 0x40000000; c = data & 0x20000000; v = data & 0x10000000; + } + + void sets(uint32 data) { + } + + void setx(uint32 data) { + } + + void setc(uint32 data) { i = data & 0x00000080; f = data & 0x00000040; m = data & 0x0000001f; + } + + operator uint32() const { + return getf() | gets() | getx() | getc(); + } + + PSR& operator=(uint32 data) { + setf(data), sets(data), setx(data), setc(data); return *this; } -} cpsr; +} cpsr, spsr; //r13 = SP (stack pointer) //r14 = LR (link register) //r15 = PC (program counter) -uint32 r[16]; +struct Register { + uint32 data; + function write; + + operator unsigned() const { + return data; + } + + Register& operator=(uint32 n) { + data = n; + if(write) write(); + } + + Register& operator+=(uint32 n) { return operator=(data + n); } + Register& operator-=(uint32 n) { return operator=(data - n); } + Register& operator&=(uint32 n) { return operator=(data & n); } + Register& operator|=(uint32 n) { return operator=(data | n); } + Register& operator^=(uint32 n) { return operator=(data ^ n); } + + void step() { + data += 4; + } +} r[16]; + +struct Pipeline { + bool reload; + struct Instruction { + uint32 opcode; + uint32 address; + }; + Instruction instruction; + Instruction prefetch; +} pipeline; uint32 instruction; -uint32 prefetch; +bool exception;