From 310ff4fa3bfd958c9f7095f83c2ee1dfd5f531b1 Mon Sep 17 00:00:00 2001 From: Tim Allen Date: Wed, 24 Jun 2015 23:21:24 +1000 Subject: [PATCH] Update to v094r30 release. byuu says: This WIP does substantially better on endrift's GBA timing tests. Still not perfect, though. But hopefully enough to get me out of dead last place. I also finally fixed the THUMB-mode ldmia bug that jchadwick reported. So, GBA emulation should be improved quite a bit, hopefully. --- emulator/emulator.hpp | 2 +- gba/cpu/cpu.cpp | 4 +- gba/cpu/dma.cpp | 4 +- gba/cpu/registers.hpp | 2 +- gba/memory/memory.cpp | 58 ++++++------- gba/memory/memory.hpp | 31 +++---- gba/memory/mmio.cpp | 4 +- gba/memory/serialization.cpp | 2 +- nall/intrinsics.hpp | 2 +- processor/arm/algorithms.cpp | 25 +++--- processor/arm/arm.cpp | 17 ++-- processor/arm/arm.hpp | 64 ++++++++------ processor/arm/disassembler.cpp | 6 +- processor/arm/disassembler.hpp | 6 +- processor/arm/instructions-arm.cpp | 101 +++++------------------ processor/arm/instructions-arm.hpp | 44 +++++----- processor/arm/instructions-thumb.cpp | 119 +++++++-------------------- processor/arm/instructions-thumb.hpp | 48 ++++++----- processor/arm/registers.cpp | 6 +- processor/arm/registers.hpp | 90 ++++++++++---------- processor/arm/serialization.cpp | 4 +- processor/arm/step.cpp | 116 ++++++++++++++++++++++++++ 22 files changed, 384 insertions(+), 371 deletions(-) create mode 100644 processor/arm/step.cpp diff --git a/emulator/emulator.hpp b/emulator/emulator.hpp index eba18649..cf7eb118 100644 --- a/emulator/emulator.hpp +++ b/emulator/emulator.hpp @@ -8,7 +8,7 @@ using namespace nall; namespace Emulator { static const string Name = "higan"; - static const string Version = "094.29"; + static const string Version = "094.30"; static const string Author = "byuu"; static const string License = "GPLv3"; static const string Website = "http://byuu.org/"; diff --git a/gba/cpu/cpu.cpp b/gba/cpu/cpu.cpp index cdcf23c3..5a51130c 100644 --- a/gba/cpu/cpu.cpp +++ b/gba/cpu/cpu.cpp @@ -76,12 +76,12 @@ void CPU::bus_idle(uint32 addr) { } uint32 CPU::bus_read(uint32 addr, uint32 size) { - step(bus.speed(addr, size)); + step(bus.wait(addr, size)); return bus.read(addr, size); } void CPU::bus_write(uint32 addr, uint32 size, uint32 word) { - step(bus.speed(addr, size)); + step(bus.wait(addr, size)); return bus.write(addr, size, word); } diff --git a/gba/cpu/dma.cpp b/gba/cpu/dma.cpp index a12121b5..11eda799 100644 --- a/gba/cpu/dma.cpp +++ b/gba/cpu/dma.cpp @@ -16,10 +16,10 @@ void CPU::dma_transfer(Registers::DMA& dma) { sequential() = false; do { - step(bus.speed(dma.run.source, size)); + step(bus.wait(dma.run.source, size)); uint32 word = bus.read(dma.run.source, size); - step(bus.speed(dma.run.target, size)); + step(bus.wait(dma.run.target, size)); bus.write(dma.run.target, size, word); sequential() = true; diff --git a/gba/cpu/registers.hpp b/gba/cpu/registers.hpp index 341cadad..f01d674c 100644 --- a/gba/cpu/registers.hpp +++ b/gba/cpu/registers.hpp @@ -150,7 +150,7 @@ struct Registers { struct WaitControl { uint2 nwait[4]; - uint2 swait[4]; + uint1 swait[4]; uint2 phi; uint1 prefetch; uint1 gametype; diff --git a/gba/memory/memory.cpp b/gba/memory/memory.cpp index 82e98cbe..b4963b63 100644 --- a/gba/memory/memory.cpp +++ b/gba/memory/memory.cpp @@ -7,13 +7,13 @@ namespace GameBoyAdvance { Bus bus; struct UnmappedMemory : Memory { - uint32 read(uint32 addr, uint32 size) { return 0u; } - void write(uint32 addr, uint32 size, uint32 word) {} + auto read(uint32 addr, uint32 size) -> uint32 { return 0; } + auto write(uint32 addr, uint32 size, uint32 word) -> void {} }; static UnmappedMemory unmappedMemory; -uint32 Bus::mirror(uint32 addr, uint32 size) { +auto Bus::mirror(uint32 addr, uint32 size) -> uint32 { uint32 base = 0; if(size) { uint32 mask = 1 << 27; //28-bit bus @@ -31,46 +31,46 @@ uint32 Bus::mirror(uint32 addr, uint32 size) { return base; } -uint32 Bus::speed(uint32 addr, uint32 size) { - if(addr & 0x08000000) { - static unsigned timing[] = {5, 4, 3, 9}; +auto Bus::wait(uint32 addr, uint32 size) -> unsigned { + switch(addr & 0x0f000000) { + case 0x00000000: return 1; + case 0x01000000: return 1; + case 0x02000000: return (16 - cpu.regs.memory.control.ewramwait) * (size == Word ? 2 : 1); + case 0x03000000: return 1; + case 0x04000000: return 2; + case 0x05000000: return 1 + (size == Word); + case 0x06000000: return 1 + (size == Word); + case 0x07000000: return 1; + default: { unsigned n = cpu.regs.wait.control.nwait[addr >> 25 & 3]; unsigned s = cpu.regs.wait.control.swait[addr >> 25 & 3]; + + static unsigned timing[] = {5, 4, 3, 9}; n = timing[n]; - switch(addr >> 25 & 3) { - case 0: s = s ? 3 : 2; break; - case 1: s = s ? 5 : 2; break; - case 2: s = s ? 9 : 2; break; - case 3: s = n; break; + switch(addr & 0x0e000000) { + case 0x08000000: s = s ? 2 : 3; break; + case 0x0a000000: s = s ? 2 : 5; break; + case 0x0c000000: s = s ? 2 : 9; break; + case 0x0e000000: s = n; break; } bool sequential = cpu.sequential(); - if((addr & 0xffff << 1) == 0) sequential = false; //N cycle on 16-bit ROM crossing page boundary (RAM S==N) + if((addr & 0x1fffe) == 0) sequential = false; //N cycle on 16-bit ROM crossing 128KB page boundary (RAM S==N) if(idleflag) sequential = false; //LDR/LDM interrupts instruction fetches - if(sequential) return s << (size == Word); //16-bit bus requires two transfers for words - if(size == Word) n += s; - return n; + unsigned clocks = sequential ? s : n; + if(size == Word) clocks += s; //16-bit bus requires two transfers for words + return clocks; } - - switch(addr >> 24 & 7) { - case 0: return 1; - case 1: return 1; - case 2: return (1 + 15 - cpu.regs.memory.control.ewramwait) << (size == Word); - case 3: return 1; - case 4: return 1; - case 5: return 1 << (size == Word); - case 6: return 1 << (size == Word); - case 7: return 1; } } -void Bus::idle(uint32 addr) { +auto Bus::idle(uint32 addr) -> void { if(addr & 0x08000000) idleflag = true; } -uint32 Bus::read(uint32 addr, uint32 size) { +auto Bus::read(uint32 addr, uint32 size) -> uint32 { idleflag = false; if(addr & 0x08000000) return cartridge.read(addr, size); @@ -89,7 +89,7 @@ uint32 Bus::read(uint32 addr, uint32 size) { } } -void Bus::write(uint32 addr, uint32 size, uint32 word) { +auto Bus::write(uint32 addr, uint32 size, uint32 word) -> void { idleflag = false; if(addr & 0x08000000) return cartridge.write(addr, size, word); @@ -108,7 +108,7 @@ void Bus::write(uint32 addr, uint32 size, uint32 word) { } } -void Bus::power() { +auto Bus::power() -> void { for(unsigned n = 0; n < 0x400; n++) mmio[n] = &unmappedMemory; idleflag = false; } diff --git a/gba/memory/memory.hpp b/gba/memory/memory.hpp index b7ef66d5..ebe80403 100644 --- a/gba/memory/memory.hpp +++ b/gba/memory/memory.hpp @@ -1,27 +1,28 @@ struct Memory { - virtual uint32 read(uint32 addr, uint32 size) = 0; - virtual void write(uint32 addr, uint32 size, uint32 word) = 0; + virtual auto read(uint32 addr, uint32 size) -> uint32 = 0; + virtual auto write(uint32 addr, uint32 size, uint32 word) -> void = 0; }; struct MMIO : Memory { - virtual uint8 read(uint32 addr) = 0; - virtual void write(uint32 addr, uint8 data) = 0; - uint32 read(uint32 addr, uint32 size); - void write(uint32 addr, uint32 size, uint32 word); + virtual auto read(uint32 addr) -> uint8 = 0; + virtual auto write(uint32 addr, uint8 data) -> void = 0; + auto read(uint32 addr, uint32 size) -> uint32; + auto write(uint32 addr, uint32 size, uint32 word) -> void; }; struct Bus : Memory { - Memory* mmio[0x400]; - bool idleflag; - static uint32 mirror(uint32 addr, uint32 size); + static auto mirror(uint32 addr, uint32 size) -> uint32; - uint32 speed(uint32 addr, uint32 size); - void idle(uint32 addr); - uint32 read(uint32 addr, uint32 size); - void write(uint32 addr, uint32 size, uint32 word); - void power(); + auto wait(uint32 addr, uint32 size) -> unsigned; + auto idle(uint32 addr) -> void; + auto read(uint32 addr, uint32 size) -> uint32; + auto write(uint32 addr, uint32 size, uint32 word) -> void; + auto power() -> void; - void serialize(serializer&); + auto serialize(serializer&) -> void; + + Memory* mmio[0x400]{nullptr}; + bool idleflag{false}; }; extern Bus bus; diff --git a/gba/memory/mmio.cpp b/gba/memory/mmio.cpp index 1fc6f422..8ad6e897 100644 --- a/gba/memory/mmio.cpp +++ b/gba/memory/mmio.cpp @@ -1,4 +1,4 @@ -uint32 MMIO::read(uint32 addr, uint32 size) { +auto MMIO::read(uint32 addr, uint32 size) -> uint32 { uint32 word = 0; switch(size) { @@ -22,7 +22,7 @@ uint32 MMIO::read(uint32 addr, uint32 size) { return word; } -void MMIO::write(uint32 addr, uint32 size, uint32 word) { +auto MMIO::write(uint32 addr, uint32 size, uint32 word) -> void { switch(size) { case Word: addr &= ~3; diff --git a/gba/memory/serialization.cpp b/gba/memory/serialization.cpp index 106ecd1b..06cc5d4e 100644 --- a/gba/memory/serialization.cpp +++ b/gba/memory/serialization.cpp @@ -1,3 +1,3 @@ -void Bus::serialize(serializer& s) { +auto Bus::serialize(serializer& s) -> void { s.integer(idleflag); } diff --git a/nall/intrinsics.hpp b/nall/intrinsics.hpp index 6c55f816..28622648 100644 --- a/nall/intrinsics.hpp +++ b/nall/intrinsics.hpp @@ -57,7 +57,7 @@ namespace nall { #if defined(_WIN32) #define PLATFORM_WINDOWS #define API_WINDOWS - #define DISPLAY_WINDOW + #define DISPLAY_WINDOWS auto Intrinsics::platform() -> Platform { return Platform::Windows; } auto Intrinsics::api() -> API { return API::Windows; } auto Intrinsics::display() -> Display { return Display::Windows; } diff --git a/processor/arm/algorithms.cpp b/processor/arm/algorithms.cpp index 8eb5d6bb..1de57563 100644 --- a/processor/arm/algorithms.cpp +++ b/processor/arm/algorithms.cpp @@ -1,4 +1,4 @@ -bool ARM::condition(uint4 condition) { +auto ARM::condition(uint4 condition) -> bool { switch(condition) { case 0: return cpsr().z == 1; //EQ (equal) case 1: return cpsr().z == 0; //NE (not equal) @@ -19,7 +19,7 @@ bool ARM::condition(uint4 condition) { } } -uint32 ARM::bit(uint32 result) { +auto ARM::bit(uint32 result) -> uint32 { if(cpsr().t || instruction() & (1 << 20)) { cpsr().n = result >> 31; cpsr().z = result == 0; @@ -28,7 +28,7 @@ uint32 ARM::bit(uint32 result) { return result; } -uint32 ARM::add(uint32 source, uint32 modify, bool carry) { +auto ARM::add(uint32 source, uint32 modify, bool carry) -> uint32 { uint32 result = source + modify + carry; if(cpsr().t || instruction() & (1 << 20)) { uint32 overflow = ~(source ^ modify) & (source ^ result); @@ -40,11 +40,16 @@ uint32 ARM::add(uint32 source, uint32 modify, bool carry) { return result; } -uint32 ARM::sub(uint32 source, uint32 modify, bool carry) { +auto ARM::sub(uint32 source, uint32 modify, bool carry) -> uint32 { return add(source, ~modify, carry); } -uint32 ARM::mul(uint32 product, uint32 multiplicand, uint32 multiplier) { +auto ARM::mul(uint32 product, uint32 multiplicand, uint32 multiplier) -> uint32 { + if((multiplier & 0xffffff00) == 0x00000000 || (multiplier & 0xffffff00 == 0xffffff00)) step(1); + else if((multiplier & 0xffff0000) == 0x00000000 || (multiplier & 0xffff0000 == 0xffff0000)) step(2); + else if((multiplier & 0xff000000) == 0x00000000 || (multiplier & 0xff000000 == 0xff000000)) step(3); + else step(4); + product += multiplicand * multiplier; if(cpsr().t || instruction() & (1 << 20)) { @@ -55,7 +60,7 @@ uint32 ARM::mul(uint32 product, uint32 multiplicand, uint32 multiplier) { return product; } -uint32 ARM::lsl(uint32 source, uint8 shift) { +auto ARM::lsl(uint32 source, uint8 shift) -> uint32 { carryout() = cpsr().c; if(shift == 0) return source; @@ -64,7 +69,7 @@ uint32 ARM::lsl(uint32 source, uint8 shift) { return source; } -uint32 ARM::lsr(uint32 source, uint8 shift) { +auto ARM::lsr(uint32 source, uint8 shift) -> uint32 { carryout() = cpsr().c; if(shift == 0) return source; @@ -73,7 +78,7 @@ uint32 ARM::lsr(uint32 source, uint8 shift) { return source; } -uint32 ARM::asr(uint32 source, uint8 shift) { +auto ARM::asr(uint32 source, uint8 shift) -> uint32 { carryout() = cpsr().c; if(shift == 0) return source; @@ -82,7 +87,7 @@ uint32 ARM::asr(uint32 source, uint8 shift) { return source; } -uint32 ARM::ror(uint32 source, uint8 shift) { +auto ARM::ror(uint32 source, uint8 shift) -> uint32 { carryout() = cpsr().c; if(shift == 0) return source; @@ -92,7 +97,7 @@ uint32 ARM::ror(uint32 source, uint8 shift) { return source; } -uint32 ARM::rrx(uint32 source) { +auto ARM::rrx(uint32 source) -> uint32 { carryout() = source & 1; return (cpsr().c << 31) | (source >> 1); } diff --git a/processor/arm/arm.cpp b/processor/arm/arm.cpp index 9621a347..5fee5ff0 100644 --- a/processor/arm/arm.cpp +++ b/processor/arm/arm.cpp @@ -7,10 +7,11 @@ namespace Processor { #include "algorithms.cpp" #include "instructions-arm.cpp" #include "instructions-thumb.cpp" +#include "step.cpp" #include "disassembler.cpp" #include "serialization.cpp" -void ARM::power() { +auto ARM::power() -> void { processor.power(); vector(0x00000000, Processor::Mode::SVC); pipeline.reload = true; @@ -23,21 +24,21 @@ void ARM::power() { instructions = 0; } -void ARM::exec() { +auto ARM::exec() -> void { cpsr().t ? thumb_step() : arm_step(); } -void ARM::idle() { +auto ARM::idle() -> void { bus_idle(r(15)); } -uint32 ARM::read(uint32 addr, uint32 size) { +auto ARM::read(uint32 addr, uint32 size) -> uint32 { uint32 word = bus_read(addr, size); sequential() = true; return word; } -uint32 ARM::load(uint32 addr, uint32 size) { +auto ARM::load(uint32 addr, uint32 size) -> uint32 { sequential() = false; uint32 word = read(addr, size); @@ -52,12 +53,12 @@ uint32 ARM::load(uint32 addr, uint32 size) { return word; } -void ARM::write(uint32 addr, uint32 size, uint32 word) { +auto ARM::write(uint32 addr, uint32 size, uint32 word) -> void { bus_write(addr, size, word); sequential() = true; } -void ARM::store(uint32 addr, uint32 size, uint32 word) { +auto ARM::store(uint32 addr, uint32 size, uint32 word) -> void { if(size == Half) { word &= 0xffff; word |= word << 16; } if(size == Byte) { word &= 0xff; word |= word << 8; word |= word << 16; } @@ -66,7 +67,7 @@ void ARM::store(uint32 addr, uint32 size, uint32 word) { sequential() = false; } -void ARM::vector(uint32 addr, Processor::Mode mode) { +auto ARM::vector(uint32 addr, Processor::Mode mode) -> void { auto psr = cpsr(); processor.setMode(mode); spsr() = psr; diff --git a/processor/arm/arm.hpp b/processor/arm/arm.hpp index 38b58d61..2ccc9466 100644 --- a/processor/arm/arm.hpp +++ b/processor/arm/arm.hpp @@ -3,44 +3,54 @@ namespace Processor { -//ARMv3 -//ARMv4TDMI +//Supported Models: +//* ARMv3 (ST018) +//* ARMv4 (ARM7TDMI) struct ARM { enum : unsigned { Byte = 8, Half = 16, Word = 32 }; + #include "registers.hpp" #include "instructions-arm.hpp" #include "instructions-thumb.hpp" #include "disassembler.hpp" - virtual void step(unsigned clocks) = 0; - virtual void bus_idle(uint32 addr) = 0; - virtual uint32 bus_read(uint32 addr, uint32 size) = 0; - virtual void bus_write(uint32 addr, uint32 size, uint32 word) = 0; - void power(); - void exec(); - void idle(); - uint32 read(uint32 addr, uint32 size); - uint32 load(uint32 addr, uint32 size); - void write(uint32 addr, uint32 size, uint32 word); - void store(uint32 addr, uint32 size, uint32 word); - void vector(uint32 addr, Processor::Mode mode); + virtual auto step(unsigned clocks) -> void = 0; + virtual auto bus_idle(uint32 addr) -> void = 0; + virtual auto bus_read(uint32 addr, uint32 size) -> uint32 = 0; + virtual auto bus_write(uint32 addr, uint32 size, uint32 word) -> void = 0; - bool condition(uint4 condition); - uint32 bit(uint32 result); - uint32 add(uint32 source, uint32 modify, bool carry); - uint32 sub(uint32 source, uint32 modify, bool carry); - uint32 mul(uint32 product, uint32 multiplicand, uint32 multiplier); - uint32 lsl(uint32 source, uint8 shift); - uint32 lsr(uint32 source, uint8 shift); - uint32 asr(uint32 source, uint8 shift); - uint32 ror(uint32 source, uint8 shift); - uint32 rrx(uint32 source); + //arm.cpp + auto power() -> void; + auto exec() -> void; + auto idle() -> void; + auto read(uint32 addr, uint32 size) -> uint32; + auto load(uint32 addr, uint32 size) -> uint32; + auto write(uint32 addr, uint32 size, uint32 word) -> void; + auto store(uint32 addr, uint32 size, uint32 word) -> void; + auto vector(uint32 addr, Processor::Mode mode) -> void; - void serialize(serializer&); + //algorithms.cpp + auto condition(uint4 condition) -> bool; + auto bit(uint32 result) -> uint32; + auto add(uint32 source, uint32 modify, bool carry) -> uint32; + auto sub(uint32 source, uint32 modify, bool carry) -> uint32; + auto mul(uint32 product, uint32 multiplicand, uint32 multiplier) -> uint32; + auto lsl(uint32 source, uint8 shift) -> uint32; + auto lsr(uint32 source, uint8 shift) -> uint32; + auto asr(uint32 source, uint8 shift) -> uint32; + auto ror(uint32 source, uint8 shift) -> uint32; + auto rrx(uint32 source) -> uint32; - bool trace; - uintmax_t instructions; + //step.cpp + auto arm_step() -> void; + auto thumb_step() -> void; + + //serialization.cpp + auto serialize(serializer&) -> void; + + bool trace{false}; + uintmax_t instructions{0}; }; } diff --git a/processor/arm/disassembler.cpp b/processor/arm/disassembler.cpp index 03e90679..e00de0ca 100644 --- a/processor/arm/disassembler.cpp +++ b/processor/arm/disassembler.cpp @@ -1,6 +1,6 @@ #ifdef PROCESSOR_ARM_HPP -string ARM::disassemble_arm_instruction(uint32 pc) { +auto ARM::disassemble_arm_instruction(uint32 pc) -> string { static string conditions[] = { "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", @@ -440,7 +440,7 @@ string ARM::disassemble_arm_instruction(uint32 pc) { return output; } -string ARM::disassemble_thumb_instruction(uint32 pc) { +auto ARM::disassemble_thumb_instruction(uint32 pc) -> string { static string conditions[] = { "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", @@ -761,7 +761,7 @@ string ARM::disassemble_thumb_instruction(uint32 pc) { return output; } -string ARM::disassemble_registers() { +auto ARM::disassemble_registers() -> string { string output; output.append( "r0:", hex<8>(r( 0)), " r1:", hex<8>(r( 1)), " r2:", hex<8>(r( 2)), " r3:", hex<8>(r( 3)), " "); output.append( "r4:", hex<8>(r( 4)), " r5:", hex<8>(r( 5)), " r6:", hex<8>(r( 6)), " r7:", hex<8>(r( 7)), " "); diff --git a/processor/arm/disassembler.hpp b/processor/arm/disassembler.hpp index 3b61de82..c98408bf 100644 --- a/processor/arm/disassembler.hpp +++ b/processor/arm/disassembler.hpp @@ -1,3 +1,3 @@ -string disassemble_arm_instruction(uint32 pc); -string disassemble_thumb_instruction(uint32 pc); -string disassemble_registers(); +auto disassemble_arm_instruction(uint32 pc) -> string; +auto disassemble_thumb_instruction(uint32 pc) -> string; +auto disassemble_registers() -> string; diff --git a/processor/arm/instructions-arm.cpp b/processor/arm/instructions-arm.cpp index 62f1a05b..62a5f2b7 100644 --- a/processor/arm/instructions-arm.cpp +++ b/processor/arm/instructions-arm.cpp @@ -1,64 +1,6 @@ #ifdef PROCESSOR_ARM_HPP -void ARM::arm_step() { - if(pipeline.reload) { - pipeline.reload = false; - r(15).data &= ~3; - - sequential() = false; - pipeline.fetch.address = r(15) & ~3; - pipeline.fetch.instruction = read(pipeline.fetch.address, Word); - - pipeline_step(); - } - - pipeline_step(); - - if(processor.irqline && cpsr().i == 0) { - vector(0x00000018, Processor::Mode::IRQ); - return; - } - - instructions++; - if(trace) { - print(disassemble_registers(), "\n"); - print(disassemble_arm_instruction(pipeline.execute.address), "\n"); - usleep(100000); - } - - if(condition(instruction() >> 28) == false) return; - - #define decode(pattern, execute) if( \ - (instruction() & std::integral_constant::value) \ - == std::integral_constant::value \ - ) return arm_op_ ## execute() - - decode("???? 0001 0010 ++++ ++++ ++++ 0001 ????", branch_exchange_register); - decode("???? 0000 00?? ???? ???? ???? 1001 ????", multiply); - decode("???? 0000 1??? ???? ???? ???? 1001 ????", multiply_long); - decode("???? 0001 0?00 ++++ ???? ---- 0000 ----", move_to_register_from_status); - decode("???? 0001 0?00 ???? ???? ---- 1001 ????", memory_swap); - decode("???? 0001 0?10 ???? ++++ ---- 0000 ????", move_to_status_from_register); - decode("???? 0011 0?10 ???? ++++ ???? ???? ????", move_to_status_from_immediate); - decode("???? 000? ?0?1 ???? ???? ---- 11?1 ????", load_register); - decode("???? 000? ?1?1 ???? ???? ???? 11?1 ????", load_immediate); - decode("???? 000? ?0?? ???? ???? ---- 1011 ????", move_half_register); - decode("???? 000? ?1?? ???? ???? ???? 1011 ????", move_half_immediate); - decode("???? 000? ???? ???? ???? ???? ???0 ????", data_immediate_shift); - decode("???? 000? ???? ???? ???? ???? 0??1 ????", data_register_shift); - decode("???? 001? ???? ???? ???? ???? ???? ????", data_immediate); - decode("???? 010? ???? ???? ???? ???? ???? ????", move_immediate_offset); - decode("???? 011? ???? ???? ???? ???? ???0 ????", move_register_offset); - decode("???? 100? ???? ???? ???? ???? ???? ????", move_multiple); - decode("???? 101? ???? ???? ???? ???? ???? ????", branch); - decode("???? 1111 ???? ???? ???? ???? ???? ????", software_interrupt); - - #undef decode - - crash = true; -} - -void ARM::arm_opcode(uint32 rm) { +auto ARM::arm_opcode(uint32 rm) { uint4 opcode = instruction() >> 21; uint1 save = instruction() >> 20; uint4 n = instruction() >> 16; @@ -91,7 +33,7 @@ void ARM::arm_opcode(uint32 rm) { } } -void ARM::arm_move_to_status(uint32 rm) { +auto ARM::arm_move_to_status(uint32 rm) { uint1 source = instruction() >> 22; uint4 field = instruction() >> 16; @@ -130,7 +72,7 @@ void ARM::arm_move_to_status(uint32 rm) { //n = rn //s = rs //m = rm -void ARM::arm_op_multiply() { +auto ARM::arm_op_multiply() { uint1 accumulate = instruction() >> 21; uint1 save = instruction() >> 20; uint4 d = instruction() >> 16; @@ -138,7 +80,6 @@ void ARM::arm_op_multiply() { uint4 s = instruction() >> 8; uint4 m = instruction(); - step(1); r(d) = mul(accumulate ? r(n) : 0u, r(m), r(s)); } @@ -153,7 +94,7 @@ void ARM::arm_op_multiply() { //l = rdlo //s = rs //m = rm -void ARM::arm_op_multiply_long() { +auto ARM::arm_op_multiply_long() { uint1 signextend = instruction() >> 22; uint1 accumulate = instruction() >> 21; uint1 save = instruction() >> 20; @@ -190,7 +131,7 @@ void ARM::arm_op_multiply_long() { //n = rn //d = rd //m = rm -void ARM::arm_op_memory_swap() { +auto ARM::arm_op_memory_swap() { uint1 byte = instruction() >> 22; uint4 n = instruction() >> 16; uint4 d = instruction() >> 12; @@ -212,7 +153,7 @@ void ARM::arm_op_memory_swap() { //n = rn //d = rd //m = rm -void ARM::arm_op_move_half_register() { +auto ARM::arm_op_move_half_register() { uint1 pre = instruction() >> 24; uint1 up = instruction() >> 23; uint1 writeback = instruction() >> 21; @@ -244,7 +185,7 @@ void ARM::arm_op_move_half_register() { //d = rd //i = immediate hi //i = immediate lo -void ARM::arm_op_move_half_immediate() { +auto ARM::arm_op_move_half_immediate() { uint1 pre = instruction() >> 24; uint1 up = instruction() >> 23; uint1 writeback = instruction() >> 21; @@ -276,7 +217,7 @@ void ARM::arm_op_move_half_immediate() { //d = rd //h = half (0 = byte) //m = rm -void ARM::arm_op_load_register() { +auto ARM::arm_op_load_register() { uint1 pre = instruction() >> 24; uint1 up = instruction() >> 23; uint1 writeback = instruction() >> 21; @@ -308,7 +249,7 @@ void ARM::arm_op_load_register() { //i = immediate hi //h = half (0 = byte) //i = immediate lo -void ARM::arm_op_load_immediate() { +auto ARM::arm_op_load_immediate() { uint1 pre = instruction() >> 24; uint1 up = instruction() >> 23; uint1 writeback = instruction() >> 21; @@ -334,7 +275,7 @@ void ARM::arm_op_load_immediate() { //c = condition //r = SPSR (0 = CPSR) //d = rd -void ARM::arm_op_move_to_register_from_status() { +auto ARM::arm_op_move_to_register_from_status() { uint1 source = instruction() >> 22; uint4 d = instruction() >> 12; @@ -352,7 +293,7 @@ void ARM::arm_op_move_to_register_from_status() { //r = SPSR (0 = CPSR) //f = field mask //m = rm -void ARM::arm_op_move_to_status_from_register() { +auto ARM::arm_op_move_to_status_from_register() { uint4 m = instruction(); arm_move_to_status(r(m)); @@ -362,7 +303,7 @@ void ARM::arm_op_move_to_status_from_register() { //cccc 0001 0010 ++++ ++++ ++++ 0001 mmmm //c = condition //m = rm -void ARM::arm_op_branch_exchange_register() { +auto ARM::arm_op_branch_exchange_register() { uint4 m = instruction(); cpsr().t = r(m) & 1; @@ -376,7 +317,7 @@ void ARM::arm_op_branch_exchange_register() { //f = field mask //r = rotate //i = immediate -void ARM::arm_op_move_to_status_from_immediate() { +auto ARM::arm_op_move_to_status_from_immediate() { uint4 rotate = instruction() >> 8; uint8 immediate = instruction(); @@ -398,7 +339,7 @@ void ARM::arm_op_move_to_status_from_immediate() { //l = shift immediate //s = shift //m = rm -void ARM::arm_op_data_immediate_shift() { +auto ARM::arm_op_data_immediate_shift() { uint1 save = instruction() >> 20; uint5 shift = instruction() >> 7; uint2 mode = instruction() >> 5; @@ -428,7 +369,7 @@ void ARM::arm_op_data_immediate_shift() { //s = rs //s = shift //m = rm -void ARM::arm_op_data_register_shift() { +auto ARM::arm_op_data_register_shift() { uint1 save = instruction() >> 20; uint4 s = instruction() >> 8; uint2 mode = instruction() >> 5; @@ -457,7 +398,7 @@ void ARM::arm_op_data_register_shift() { //d = rd //s = shift immediate //i = immediate -void ARM::arm_op_data_immediate() { +auto ARM::arm_op_data_immediate() { uint1 save = instruction() >> 20; uint4 shift = instruction() >> 8; uint8 immediate = instruction(); @@ -482,7 +423,7 @@ void ARM::arm_op_data_immediate() { //n = rn //d = rd //i = immediate -void ARM::arm_op_move_immediate_offset() { +auto ARM::arm_op_move_immediate_offset() { uint1 pre = instruction() >> 24; uint1 up = instruction() >> 23; uint1 byte = instruction() >> 22; @@ -517,7 +458,7 @@ void ARM::arm_op_move_immediate_offset() { //l = shift immediate //s = shift mode //m = rm -void ARM::arm_op_move_register_offset() { +auto ARM::arm_op_move_register_offset() { uint1 pre = instruction() >> 24; uint1 up = instruction() >> 23; uint1 byte = instruction() >> 22; @@ -558,7 +499,7 @@ void ARM::arm_op_move_register_offset() { //l = load (0 = save) //n = rn //l = register list -void ARM::arm_op_move_multiple() { +auto ARM::arm_op_move_multiple() { uint1 pre = instruction() >> 24; uint1 up = instruction() >> 23; uint1 s = instruction() >> 22; @@ -612,7 +553,7 @@ void ARM::arm_op_move_multiple() { //c = condition //l = link //d = displacement (24-bit signed) -void ARM::arm_op_branch() { +auto ARM::arm_op_branch() { uint1 link = instruction() >> 24; int24 displacement = instruction(); @@ -624,7 +565,7 @@ void ARM::arm_op_branch() { //cccc 1111 iiii iiii iiii iiii iiii iiii //c = condition //i = immediate -void ARM::arm_op_software_interrupt() { +auto ARM::arm_op_software_interrupt() { uint24 immediate = instruction(); vector(0x00000008, Processor::Mode::SVC); diff --git a/processor/arm/instructions-arm.hpp b/processor/arm/instructions-arm.hpp index b7a9870c..57118caa 100644 --- a/processor/arm/instructions-arm.hpp +++ b/processor/arm/instructions-arm.hpp @@ -1,26 +1,24 @@ -void arm_step(); +auto arm_opcode(uint32 rm); +auto arm_move_to_status(uint32 rm); -void arm_opcode(uint32 rm); -void arm_move_to_status(uint32 rm); +auto arm_op_multiply(); +auto arm_op_multiply_long(); +auto arm_op_memory_swap(); +auto arm_op_move_half_register(); +auto arm_op_move_half_immediate(); +auto arm_op_load_register(); +auto arm_op_load_immediate(); -void arm_op_multiply(); -void arm_op_multiply_long(); -void arm_op_memory_swap(); -void arm_op_move_half_register(); -void arm_op_move_half_immediate(); -void arm_op_load_register(); -void arm_op_load_immediate(); +auto arm_op_move_to_register_from_status(); +auto arm_op_move_to_status_from_register(); +auto arm_op_branch_exchange_register(); -void arm_op_move_to_register_from_status(); -void arm_op_move_to_status_from_register(); -void arm_op_branch_exchange_register(); - -void arm_op_move_to_status_from_immediate(); -void arm_op_data_immediate_shift(); -void arm_op_data_register_shift(); -void arm_op_data_immediate(); -void arm_op_move_immediate_offset(); -void arm_op_move_register_offset(); -void arm_op_move_multiple(); -void arm_op_branch(); -void arm_op_software_interrupt(); +auto arm_op_move_to_status_from_immediate(); +auto arm_op_data_immediate_shift(); +auto arm_op_data_register_shift(); +auto arm_op_data_immediate(); +auto arm_op_move_immediate_offset(); +auto arm_op_move_register_offset(); +auto arm_op_move_multiple(); +auto arm_op_branch(); +auto arm_op_software_interrupt(); diff --git a/processor/arm/instructions-thumb.cpp b/processor/arm/instructions-thumb.cpp index b795d4cd..78c58e8d 100644 --- a/processor/arm/instructions-thumb.cpp +++ b/processor/arm/instructions-thumb.cpp @@ -1,65 +1,6 @@ #ifdef PROCESSOR_ARM_HPP -void ARM::thumb_step() { - if(pipeline.reload) { - pipeline.reload = false; - r(15).data &= ~1; - - sequential() = false; - pipeline.fetch.address = r(15) & ~1; - pipeline.fetch.instruction = read(pipeline.fetch.address, Half); - - pipeline_step(); - } - - pipeline_step(); - - if(processor.irqline && cpsr().i == 0) { - vector(0x00000018, Processor::Mode::IRQ); - r(14) += 2; - return; - } - - instructions++; - if(trace) { - print(disassemble_registers(), "\n"); - print(disassemble_thumb_instruction(pipeline.execute.address), "\n"); - } - - #define decode(pattern, execute) if( \ - (instruction() & std::integral_constant::value) \ - == std::integral_constant::value \ - ) return thumb_op_ ## execute() - - decode("0001 10?? ???? ????", adjust_register); - decode("0001 11?? ???? ????", adjust_immediate); - decode("000? ???? ???? ????", shift_immediate); - decode("001? ???? ???? ????", immediate); - decode("0100 00?? ???? ????", alu); - decode("0100 0111 0??? ?---", branch_exchange); - decode("0100 01?? ???? ????", alu_hi); - decode("0100 1??? ???? ????", load_literal); - decode("0101 ???? ???? ????", move_register_offset); - decode("0110 ???? ???? ????", move_word_immediate); - decode("0111 ???? ???? ????", move_byte_immediate); - decode("1000 ???? ???? ????", move_half_immediate); - decode("1001 ???? ???? ????", move_stack); - decode("1010 ???? ???? ????", add_register_hi); - decode("1011 0000 ???? ????", adjust_stack); - decode("1011 ?10? ???? ????", stack_multiple); - decode("1100 ???? ???? ????", move_multiple); - decode("1101 1111 ???? ????", software_interrupt); - decode("1101 ???? ???? ????", branch_conditional); - decode("1110 0??? ???? ????", branch_short); - decode("1111 0??? ???? ????", branch_long_prefix); - decode("1111 1??? ???? ????", branch_long_suffix); - - #undef decode - - crash = true; -} - -void ARM::thumb_opcode(uint4 opcode, uint4 d, uint4 m) { +auto ARM::thumb_opcode(uint4 opcode, uint4 d, uint4 m) { switch(opcode) { case 0: r(d) = bit(r(d) & r(m)); break; //AND case 1: r(d) = bit(r(d) ^ r(m)); break; //EOR @@ -74,7 +15,7 @@ void ARM::thumb_opcode(uint4 opcode, uint4 d, uint4 m) { case 10: sub(r(d), r(m), 1); break; //CMP case 11: add(r(d), r(m), 0); break; //CMN case 12: r(d) = bit(r(d) | r(m)); break; //ORR - case 13: r(d) = mul(0, r(d), r(m)); break; //MUL + case 13: r(d) = mul(0, r(m), r(d)); break; //MUL case 14: r(d) = bit(r(d) & ~r(m)); break; //BIC case 15: r(d) = bit(~r(m)); break; //MVN } @@ -86,7 +27,7 @@ void ARM::thumb_opcode(uint4 opcode, uint4 d, uint4 m) { //m = rm //n = rn //d = rd -void ARM::thumb_op_adjust_register() { +auto ARM::thumb_op_adjust_register() { uint1 opcode = instruction() >> 9; uint3 m = instruction() >> 6; uint3 n = instruction() >> 3; @@ -104,7 +45,7 @@ void ARM::thumb_op_adjust_register() { //i = immediate //n = rn //d = rd -void ARM::thumb_op_adjust_immediate() { +auto ARM::thumb_op_adjust_immediate() { uint1 opcode = instruction() >> 9; uint3 immediate = instruction() >> 6; uint3 n = instruction() >> 3; @@ -122,7 +63,7 @@ void ARM::thumb_op_adjust_immediate() { //i = immediate //m = rm //d = rd -void ARM::thumb_op_shift_immediate() { +auto ARM::thumb_op_shift_immediate() { uint2 opcode = instruction() >> 11; uint5 immediate = instruction() >> 6; uint3 m = instruction() >> 3; @@ -140,7 +81,7 @@ void ARM::thumb_op_shift_immediate() { //o = opcode //r = (rd,rn) //i = immediate -void ARM::thumb_op_immediate() { +auto ARM::thumb_op_immediate() { uint2 opcode = instruction() >> 11; uint3 d = instruction() >> 8; uint8 immediate = instruction(); @@ -158,7 +99,7 @@ void ARM::thumb_op_immediate() { //o = opcode //m = rm //d = rd -void ARM::thumb_op_alu() { +auto ARM::thumb_op_alu() { uint4 opcode = instruction() >> 6; uint3 m = instruction() >> 3; uint3 d = instruction(); @@ -169,7 +110,7 @@ void ARM::thumb_op_alu() { //bx rm //0100 0111 0mmm m--- //m = rm -void ARM::thumb_op_branch_exchange() { +auto ARM::thumb_op_branch_exchange() { uint4 m = instruction() >> 3; cpsr().t = r(m) & 1; @@ -181,7 +122,7 @@ void ARM::thumb_op_branch_exchange() { //o = opcode //M:m = rm //D:d = rd -void ARM::thumb_op_alu_hi() { +auto ARM::thumb_op_alu_hi() { uint2 opcode = instruction() >> 8; uint4 m = instruction() >> 3; uint3 dl = instruction(); @@ -199,7 +140,7 @@ void ARM::thumb_op_alu_hi() { //0100 1ddd oooo oooo //d = rd //o = offset -void ARM::thumb_op_load_literal() { +auto ARM::thumb_op_load_literal() { uint3 d = instruction() >> 8; uint8 displacement = instruction(); @@ -213,7 +154,7 @@ void ARM::thumb_op_load_literal() { //m = rm //n = rn //d = rd -void ARM::thumb_op_move_register_offset() { +auto ARM::thumb_op_move_register_offset() { uint3 opcode = instruction() >> 9; uint3 m = instruction() >> 6; uint3 n = instruction() >> 3; @@ -237,7 +178,7 @@ void ARM::thumb_op_move_register_offset() { //o = offset //n = rn //d = rd -void ARM::thumb_op_move_word_immediate() { +auto ARM::thumb_op_move_word_immediate() { uint1 l = instruction() >> 11; uint5 offset = instruction() >> 6; uint3 n = instruction() >> 3; @@ -253,7 +194,7 @@ void ARM::thumb_op_move_word_immediate() { //o = offset //n = rn //d = rd -void ARM::thumb_op_move_byte_immediate() { +auto ARM::thumb_op_move_byte_immediate() { uint1 l = instruction() >> 11; uint5 offset = instruction() >> 6; uint3 n = instruction() >> 3; @@ -269,7 +210,7 @@ void ARM::thumb_op_move_byte_immediate() { //o = offset //n = rn //d = rd -void ARM::thumb_op_move_half_immediate() { +auto ARM::thumb_op_move_half_immediate() { uint1 l = instruction() >> 11; uint5 offset = instruction() >> 6; uint3 n = instruction() >> 3; @@ -284,7 +225,7 @@ void ARM::thumb_op_move_half_immediate() { //l = load //d = rd //i = immediate -void ARM::thumb_op_move_stack() { +auto ARM::thumb_op_move_stack() { uint1 l = instruction() >> 11; uint3 d = instruction() >> 8; uint8 immediate = instruction(); @@ -298,7 +239,7 @@ void ARM::thumb_op_move_stack() { //s = sp (0 = pc) //d = rd //i = immediate -void ARM::thumb_op_add_register_hi() { +auto ARM::thumb_op_add_register_hi() { uint1 sp = instruction() >> 11; uint3 d = instruction() >> 8; uint8 immediate = instruction(); @@ -311,7 +252,7 @@ void ARM::thumb_op_add_register_hi() { //1011 0000 oiii iiii //o = opcode //i = immediate -void ARM::thumb_op_adjust_stack() { +auto ARM::thumb_op_adjust_stack() { uint1 opcode = instruction() >> 7; uint7 immediate = instruction(); @@ -325,7 +266,7 @@ void ARM::thumb_op_adjust_stack() { //o = opcode (0 = push, 1 = pop) //r = push lr -or- pop pc //l = register list -void ARM::thumb_op_stack_multiple() { +auto ARM::thumb_op_stack_multiple() { uint1 l = instruction() >> 11; uint1 branch = instruction() >> 8; uint8 list = instruction(); @@ -336,7 +277,7 @@ void ARM::thumb_op_stack_multiple() { sequential() = false; for(unsigned m = 0; m < 8; m++) { - if(list & (1 << m)) { + if(list & 1 << m) { if(l == 1) r(m) = read(sp, Word); //POP if(l == 0) write(sp, Word, r(m)); //PUSH sp += 4; @@ -360,27 +301,29 @@ void ARM::thumb_op_stack_multiple() { //l = load (0 = save) //n = rn //l = register list -void ARM::thumb_op_move_multiple() { +auto ARM::thumb_op_move_multiple() { uint1 l = instruction() >> 11; uint3 n = instruction() >> 8; uint8 list = instruction(); + uint32 rn = r(n); //rn may be in register list; so we must cache it sequential() = false; for(unsigned m = 0; m < 8; m++) { - if(list & (1 << m)) { - if(l == 1) r(m) = read(r(n), Word); //LDMIA - if(l == 0) write(r(n), Word, r(m)); //STMIA - r(n) += 4; + if(list & 1 << m) { + if(l == 1) r(m) = read(rn, Word); //LDMIA + if(l == 0) write(rn, Word, r(m)); //STMIA + rn += 4; } } + if(l == 0 || (list & 1 << n) == 0) r(n) = rn; //update rn on save or when not in register list if(l == 1) idle(); } //swi #immediate //1101 1111 iiii iiii //i = immediate -void ARM::thumb_op_software_interrupt() { +auto ARM::thumb_op_software_interrupt() { uint8 immediate = instruction(); vector(0x00000008, Processor::Mode::SVC); @@ -390,7 +333,7 @@ void ARM::thumb_op_software_interrupt() { //1101 cccc dddd dddd //c = condition //d = displacement -void ARM::thumb_op_branch_conditional() { +auto ARM::thumb_op_branch_conditional() { uint4 flagcondition = instruction() >> 8; int8 displacement = instruction(); @@ -401,7 +344,7 @@ void ARM::thumb_op_branch_conditional() { //b address //1110 0ooo oooo oooo //o = offset -void ARM::thumb_op_branch_short() { +auto ARM::thumb_op_branch_short() { int11 displacement = instruction(); r(15) += displacement * 2; @@ -410,7 +353,7 @@ void ARM::thumb_op_branch_short() { //bl address //1111 0ooo oooo oooo //o = offset -void ARM::thumb_op_branch_long_prefix() { +auto ARM::thumb_op_branch_long_prefix() { int11 offsethi = instruction(); r(14) = r(15) + ((offsethi * 2) << 11); @@ -419,7 +362,7 @@ void ARM::thumb_op_branch_long_prefix() { //bl address //1111 1ooo oooo oooo //o = offset -void ARM::thumb_op_branch_long_suffix() { +auto ARM::thumb_op_branch_long_suffix() { uint11 offsetlo = instruction(); r(15) = r(14) + (offsetlo * 2); diff --git a/processor/arm/instructions-thumb.hpp b/processor/arm/instructions-thumb.hpp index 64baec35..4f260986 100644 --- a/processor/arm/instructions-thumb.hpp +++ b/processor/arm/instructions-thumb.hpp @@ -1,26 +1,24 @@ -void thumb_step(); +auto thumb_opcode(uint4 opcode, uint4 d, uint4 s); -void thumb_opcode(uint4 opcode, uint4 d, uint4 s); - -void thumb_op_adjust_register(); -void thumb_op_adjust_immediate(); -void thumb_op_shift_immediate(); -void thumb_op_immediate(); -void thumb_op_alu(); -void thumb_op_branch_exchange(); -void thumb_op_alu_hi(); -void thumb_op_load_literal(); -void thumb_op_move_register_offset(); -void thumb_op_move_word_immediate(); -void thumb_op_move_byte_immediate(); -void thumb_op_move_half_immediate(); -void thumb_op_move_stack(); -void thumb_op_add_register_hi(); -void thumb_op_adjust_stack(); -void thumb_op_stack_multiple(); -void thumb_op_move_multiple(); -void thumb_op_software_interrupt(); -void thumb_op_branch_conditional(); -void thumb_op_branch_short(); -void thumb_op_branch_long_prefix(); -void thumb_op_branch_long_suffix(); +auto thumb_op_adjust_register(); +auto thumb_op_adjust_immediate(); +auto thumb_op_shift_immediate(); +auto thumb_op_immediate(); +auto thumb_op_alu(); +auto thumb_op_branch_exchange(); +auto thumb_op_alu_hi(); +auto thumb_op_load_literal(); +auto thumb_op_move_register_offset(); +auto thumb_op_move_word_immediate(); +auto thumb_op_move_byte_immediate(); +auto thumb_op_move_half_immediate(); +auto thumb_op_move_stack(); +auto thumb_op_add_register_hi(); +auto thumb_op_adjust_stack(); +auto thumb_op_stack_multiple(); +auto thumb_op_move_multiple(); +auto thumb_op_software_interrupt(); +auto thumb_op_branch_conditional(); +auto thumb_op_branch_short(); +auto thumb_op_branch_long_prefix(); +auto thumb_op_branch_long_suffix(); diff --git a/processor/arm/registers.cpp b/processor/arm/registers.cpp index e6a3539d..bb924bae 100644 --- a/processor/arm/registers.cpp +++ b/processor/arm/registers.cpp @@ -1,6 +1,6 @@ #ifdef PROCESSOR_ARM_HPP -void ARM::Processor::power() { +auto ARM::Processor::power() -> void { r0 = r1 = r2 = r3 = r4 = r5 = r6 = r7 = 0; usr.r8 = usr.r9 = usr.r10 = usr.r11 = usr.r12 = usr.sp = usr.lr = 0; fiq.r8 = fiq.r9 = fiq.r10 = fiq.r11 = fiq.r12 = fiq.sp = fiq.lr = 0; @@ -34,7 +34,7 @@ void ARM::Processor::power() { r[15] = &pc; } -void ARM::Processor::setMode(Mode mode) { +auto ARM::Processor::setMode(Mode mode) -> void { cpsr.m = 0x10 | (unsigned)mode; if(mode == Mode::FIQ) { @@ -61,7 +61,7 @@ void ARM::Processor::setMode(Mode mode) { } } -void ARM::pipeline_step() { +auto ARM::pipeline_step() -> void { pipeline.execute = pipeline.decode; pipeline.decode = pipeline.fetch; diff --git a/processor/arm/registers.hpp b/processor/arm/registers.hpp index 37d8300a..e58d690d 100644 --- a/processor/arm/registers.hpp +++ b/processor/arm/registers.hpp @@ -1,39 +1,30 @@ struct GPR { - uint32 data; - function modify; - inline operator uint32() const { return data; } - inline GPR& operator=(uint32 n) { data = n; if(modify) modify(); return *this; } - inline GPR& operator=(const GPR& source) { return operator=(source.data); } + inline auto operator=(uint32 n) { data = n; if(modify) modify(); return *this; } + inline auto operator=(const GPR& source) { return operator=(source.data); } - inline GPR& operator &=(uint32 n) { return operator=(data & n); } - inline GPR& operator |=(uint32 n) { return operator=(data | n); } - inline GPR& operator ^=(uint32 n) { return operator=(data ^ n); } - inline GPR& operator +=(uint32 n) { return operator=(data + n); } - inline GPR& operator -=(uint32 n) { return operator=(data - n); } - inline GPR& operator *=(uint32 n) { return operator=(data * n); } - inline GPR& operator /=(uint32 n) { return operator=(data / n); } - inline GPR& operator %=(uint32 n) { return operator=(data % n); } - inline GPR& operator<<=(uint32 n) { return operator=(data << n); } - inline GPR& operator>>=(uint32 n) { return operator=(data >> n); } + inline auto operator &=(uint32 n) { return operator=(data & n); } + inline auto operator |=(uint32 n) { return operator=(data | n); } + inline auto operator ^=(uint32 n) { return operator=(data ^ n); } + inline auto operator +=(uint32 n) { return operator=(data + n); } + inline auto operator -=(uint32 n) { return operator=(data - n); } + inline auto operator *=(uint32 n) { return operator=(data * n); } + inline auto operator /=(uint32 n) { return operator=(data / n); } + inline auto operator %=(uint32 n) { return operator=(data % n); } + inline auto operator<<=(uint32 n) { return operator=(data << n); } + inline auto operator>>=(uint32 n) { return operator=(data >> n); } + + uint32 data{0}; + function modify; }; struct PSR { - bool n; //negative - bool z; //zero - bool c; //carry - bool v; //overflow - bool i; //irq - bool f; //fiq - bool t; //thumb - unsigned m; //mode - inline operator uint32() const { return (n << 31) + (z << 30) + (c << 29) + (v << 28) + (i << 7) + (f << 6) + (t << 5) + (m << 0); } - inline PSR& operator=(uint32 d) { + inline auto operator=(uint32 d) { n = d & (1 << 31); z = d & (1 << 30); c = d & (1 << 29); @@ -45,15 +36,24 @@ struct PSR { return *this; } - void serialize(serializer&); + auto serialize(serializer&) -> void; + + bool n{false}; //negative + bool z{false}; //zero + bool c{false}; //carry + bool v{false}; //overflow + bool i{false}; //irq + bool f{false}; //fiq + bool t{false}; //thumb + unsigned m{0}; //mode }; struct Pipeline { - bool reload; + bool reload{false}; struct Instruction { - uint32 address; - uint32 instruction; + uint32 address{0}; + uint32 instruction{0}; }; Instruction execute; @@ -105,29 +105,29 @@ struct Processor { GPR pc; PSR cpsr; - bool carryout; - bool sequential; - bool irqline; + bool carryout{false}; + bool sequential{false}; + bool irqline{false}; GPR* r[16]; PSR* spsr; - void power(); - void setMode(Mode); + auto power() -> void; + auto setMode(Mode) -> void; }; Processor processor; Pipeline pipeline; -bool crash; +bool crash{false}; -void pipeline_step(); +auto pipeline_step() -> void; -alwaysinline GPR& r(unsigned n) { return *processor.r[n]; } -alwaysinline PSR& cpsr() { return processor.cpsr; } -alwaysinline PSR& spsr() { return *processor.spsr; } -alwaysinline bool& carryout() { return processor.carryout; } -alwaysinline bool& sequential() { return processor.sequential; } -alwaysinline uint32 instruction() { return pipeline.execute.instruction; } -alwaysinline Processor::Mode mode() { return (Processor::Mode)processor.cpsr.m; } -alwaysinline bool privilegedmode() const { return (Processor::Mode)processor.cpsr.m != Processor::Mode::USR; } -alwaysinline bool exceptionmode() const { return privilegedmode() && (Processor::Mode)processor.cpsr.m != Processor::Mode::SYS; } +alwaysinline auto r(unsigned n) -> GPR& { return *processor.r[n]; } +alwaysinline auto cpsr() -> PSR& { return processor.cpsr; } +alwaysinline auto spsr() -> PSR& { return *processor.spsr; } +alwaysinline auto carryout() -> bool& { return processor.carryout; } +alwaysinline auto sequential() -> bool& { return processor.sequential; } +alwaysinline auto instruction() -> uint32 { return pipeline.execute.instruction; } +alwaysinline auto mode() -> Processor::Mode { return (Processor::Mode)processor.cpsr.m; } +alwaysinline auto privilegedmode() const -> bool { return (Processor::Mode)processor.cpsr.m != Processor::Mode::USR; } +alwaysinline auto exceptionmode() const -> bool { return privilegedmode() && (Processor::Mode)processor.cpsr.m != Processor::Mode::SYS; } diff --git a/processor/arm/serialization.cpp b/processor/arm/serialization.cpp index b48ff2f8..d45123f7 100644 --- a/processor/arm/serialization.cpp +++ b/processor/arm/serialization.cpp @@ -1,4 +1,4 @@ -void ARM::PSR::serialize(serializer& s) { +auto ARM::PSR::serialize(serializer& s) -> void { s.integer(n); s.integer(z); s.integer(c); @@ -9,7 +9,7 @@ void ARM::PSR::serialize(serializer& s) { s.integer(m); } -void ARM::serialize(serializer& s) { +auto ARM::serialize(serializer& s) -> void { s.integer(processor.r0.data); s.integer(processor.r1.data); s.integer(processor.r2.data); diff --git a/processor/arm/step.cpp b/processor/arm/step.cpp new file mode 100644 index 00000000..1d6fe8e6 --- /dev/null +++ b/processor/arm/step.cpp @@ -0,0 +1,116 @@ +auto ARM::arm_step() -> void { + if(pipeline.reload) { + pipeline.reload = false; + r(15).data &= ~3; + + sequential() = false; + pipeline.fetch.address = r(15) & ~3; + pipeline.fetch.instruction = read(pipeline.fetch.address, Word); + + pipeline_step(); + } + + pipeline_step(); + + if(processor.irqline && cpsr().i == 0) { + vector(0x00000018, Processor::Mode::IRQ); + return; + } + + instructions++; + if(trace) { + print(disassemble_registers(), "\n"); + print(disassemble_arm_instruction(pipeline.execute.address), "\n"); + usleep(100000); + } + + if(condition(instruction() >> 28) == false) return; + + #define decode(pattern, execute) if( \ + (instruction() & std::integral_constant::value) \ + == std::integral_constant::value \ + ) return arm_op_ ## execute() + + decode("???? 0001 0010 ++++ ++++ ++++ 0001 ????", branch_exchange_register); + decode("???? 0000 00?? ???? ???? ???? 1001 ????", multiply); + decode("???? 0000 1??? ???? ???? ???? 1001 ????", multiply_long); + decode("???? 0001 0?00 ++++ ???? ---- 0000 ----", move_to_register_from_status); + decode("???? 0001 0?00 ???? ???? ---- 1001 ????", memory_swap); + decode("???? 0001 0?10 ???? ++++ ---- 0000 ????", move_to_status_from_register); + decode("???? 0011 0?10 ???? ++++ ???? ???? ????", move_to_status_from_immediate); + decode("???? 000? ?0?1 ???? ???? ---- 11?1 ????", load_register); + decode("???? 000? ?1?1 ???? ???? ???? 11?1 ????", load_immediate); + decode("???? 000? ?0?? ???? ???? ---- 1011 ????", move_half_register); + decode("???? 000? ?1?? ???? ???? ???? 1011 ????", move_half_immediate); + decode("???? 000? ???? ???? ???? ???? ???0 ????", data_immediate_shift); + decode("???? 000? ???? ???? ???? ???? 0??1 ????", data_register_shift); + decode("???? 001? ???? ???? ???? ???? ???? ????", data_immediate); + decode("???? 010? ???? ???? ???? ???? ???? ????", move_immediate_offset); + decode("???? 011? ???? ???? ???? ???? ???0 ????", move_register_offset); + decode("???? 100? ???? ???? ???? ???? ???? ????", move_multiple); + decode("???? 101? ???? ???? ???? ???? ???? ????", branch); + decode("???? 1111 ???? ???? ???? ???? ???? ????", software_interrupt); + + #undef decode + + crash = true; +} + +auto ARM::thumb_step() -> void { + if(pipeline.reload) { + pipeline.reload = false; + r(15).data &= ~1; + + sequential() = false; + pipeline.fetch.address = r(15) & ~1; + pipeline.fetch.instruction = read(pipeline.fetch.address, Half); + + pipeline_step(); + } + + pipeline_step(); + + if(processor.irqline && cpsr().i == 0) { + vector(0x00000018, Processor::Mode::IRQ); + r(14) += 2; + return; + } + + instructions++; + if(trace) { + print(disassemble_registers(), "\n"); + print(disassemble_thumb_instruction(pipeline.execute.address), "\n"); + } + + #define decode(pattern, execute) if( \ + (instruction() & std::integral_constant::value) \ + == std::integral_constant::value \ + ) return thumb_op_ ## execute() + + decode("0001 10?? ???? ????", adjust_register); + decode("0001 11?? ???? ????", adjust_immediate); + decode("000? ???? ???? ????", shift_immediate); + decode("001? ???? ???? ????", immediate); + decode("0100 00?? ???? ????", alu); + decode("0100 0111 0??? ?---", branch_exchange); + decode("0100 01?? ???? ????", alu_hi); + decode("0100 1??? ???? ????", load_literal); + decode("0101 ???? ???? ????", move_register_offset); + decode("0110 ???? ???? ????", move_word_immediate); + decode("0111 ???? ???? ????", move_byte_immediate); + decode("1000 ???? ???? ????", move_half_immediate); + decode("1001 ???? ???? ????", move_stack); + decode("1010 ???? ???? ????", add_register_hi); + decode("1011 0000 ???? ????", adjust_stack); + decode("1011 ?10? ???? ????", stack_multiple); + decode("1100 ???? ???? ????", move_multiple); + decode("1101 1111 ???? ????", software_interrupt); + decode("1101 ???? ???? ????", branch_conditional); + decode("1110 0??? ???? ????", branch_short); + decode("1111 0??? ???? ????", branch_long_prefix); + decode("1111 1??? ???? ????", branch_long_suffix); + + #undef decode + + crash = true; +}