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.
This commit is contained in:
Tim Allen 2015-06-24 23:21:24 +10:00
parent 83f684c66c
commit 310ff4fa3b
22 changed files with 384 additions and 371 deletions

View File

@ -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/";

View File

@ -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);
}

View File

@ -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;

View File

@ -150,7 +150,7 @@ struct Registers {
struct WaitControl {
uint2 nwait[4];
uint2 swait[4];
uint1 swait[4];
uint2 phi;
uint1 prefetch;
uint1 gametype;

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -1,3 +1,3 @@
void Bus::serialize(serializer& s) {
auto Bus::serialize(serializer& s) -> void {
s.integer(idleflag);
}

View File

@ -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; }

View File

@ -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);
}

View File

@ -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;

View File

@ -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};
};
}

View File

@ -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)), " ");

View File

@ -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;

View File

@ -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<uint32, bit::mask(pattern)>::value) \
== std::integral_constant<uint32, bit::test(pattern)>::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);

View File

@ -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();

View File

@ -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<uint32, bit::mask(pattern)>::value) \
== std::integral_constant<uint32, bit::test(pattern)>::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);

View File

@ -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();

View File

@ -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;

View File

@ -1,39 +1,30 @@
struct GPR {
uint32 data;
function<void ()> 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<void ()> 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; }

View File

@ -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);

116
processor/arm/step.cpp Normal file
View File

@ -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<uint32, bit::mask(pattern)>::value) \
== std::integral_constant<uint32, bit::test(pattern)>::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<uint32, bit::mask(pattern)>::value) \
== std::integral_constant<uint32, bit::test(pattern)>::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;
}